36

我有一个通过调用构造函数来实例化的类(ABC 类)。ABC 类又具有一个使用自动连线注入的辅助类(XYZ 类)。

我们是一个基于 Spring MVC 的应用程序,在服务器启动时我没有看到任何异常。

但我仍然看到 XYZ 类为空。是不是因为 Class ABC 没有被 Spring Container 实例化?

在这种情况下,我如何使用自动接线?

谢谢。

4

10 回答 10

47

您可以使用这种方式在非spring bean类中使用spring bean

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextUtils implements ApplicationContextAware {
     
      private static ApplicationContext ctx;
     
      @Override
      public void setApplicationContext(ApplicationContext appContext) {
        ctx = appContext;
      }
     
      public static ApplicationContext getApplicationContext() {
        return ctx;
      }
}

现在就可以通过getApplicationContext()这个方法来获取applicationcontext对象了。

从 applicationcontext 你可以得到这样的spring bean对象:

ApplicationContext appCtx = ApplicationContextUtils.getApplicationContext();
String strFromContext = appCtx.getBean(beanName, String.class);
于 2013-08-28T11:06:46.157 回答
12

自动装配不起作用,因为 ABC 类不是由 Spring 管理的。您可以通过使用类定义上方的@Component 注释(@Component、@Service、@Controller 等)之一,然后在应用程序上下文 XML 中使用 context:component-scan 来让 Spring 管理 ABC,或者去老学校和只需在应用程序上下文中直接定义 bean。

如果由于某种原因您不能让 Spring 管理 ABC 类,您可以使用以下方式在 ABC 中加载应用程序上下文:

ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");

然后使用:

XYZ someXyz = (XYZ) context.getBean("MyXYZ");

手动设置 bean 值。

于 2013-08-21T02:01:16.547 回答
4

正确:你不能只叫new一个班级然后把它全部连接起来;Spring 必须管理 bean 才能发挥其所有魔力。

如果您可以发布有关您的用例的更多详细信息,我们可能会建议有用的选项。

于 2013-08-21T01:45:12.930 回答
4

您可以在要自动装配其他 bean 的类中使用 Spring 的 @Configurable 注释。此外,您需要使用 @EnableSpringConfigured 注释任何配置 bean,以便 Spring 知道您的可配置 bean。

@EnableSpringConfigured 文档

public @interface EnableSpringConfigured 向当前应用程序上下文发出信号,以将依赖注入应用到在 Spring bean 工厂之外实例化的非托管类(通常是使用 @Configurable 注释注释的类)。类似于 Spring 的 XML 元素中的功能。通常与@EnableLoadTimeWeaving 结合使用。

@Configurable(autowire = Autowire.BY_TYPE)
public class ABC {
    @Autowire private XYZ xyz;
    ...
}

@Configuration
@EnableSpringConfigured
public class Application {
    ...
}

public class MyClass {
    public void doSomething() {
        ABC abc = new ABC(); // XYZ is successfully autowired
        ...
    }
}
于 2016-09-13T18:31:58.710 回答
3

对于像我这样做基本 Spring Boot 并且不熟悉术语的菜鸟:

  • 您的服务、存储库等都是 Bean
  • 您可以从 ApplicationContext 获取您的 Bean

Ashish 的回答对我有用,但这篇文章提供了更多解释。

如果您不知道所需 bean 的名称,请尝试查看此数组:

String[] names = context.getBeanDefinitionNames();

如果您对“组件扫描”和配置文件的讨论感到困惑,那么了解@SpringBootApplication 注解(您可能会在 main() 方法附近找到)隐式调用 @Configuration 和 @ComponentScan 可能会有所帮助。

这意味着该包中的所有文件(在主类顶部声明)都由 Spring 拾取,并且您想要添加的任何 bean 都可以与 main() 一起编写

于 2018-08-22T11:19:05.170 回答
2

简而言之,是的,ABC 没有被注入 XYZ,因为 Spring 没有管理 ABC。Spring 无法配置它不知道的对象。

您可以通过使用@Service或注释来管理 ABC @Component。请注意,为了让 Spring 接收这些注释,Spring 必须打开自动扫描:

<context:component-scan base-package="com.mypackage.awesomeproject" />
于 2013-08-21T01:45:27.597 回答
1

第一个问题 - 是的你有 null 因为类不是用 spring 启动的第二个问题 - 我认为你可以使用 aspectj 支持http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop .html#aop-using-aspectj

于 2013-08-21T07:52:50.380 回答
0

您可以使用注释ABC对类进行@Configurable注释。XYZ然后 Spring IOC 会将实例注入到ABC类中。它通常与 AspectJ 一起使用AnnotationBeanConfigurerAspect

于 2013-08-21T08:56:58.853 回答
0

Spring 有 util 类

 BeanUtils.instantiateClass(clazz)
 BeanUtils.instantiate(clazz)

 YouClass ins = BeanUtils.instantiate(YouClass.class)

https://docs.spring.io/autorepo/docs/spring/4.0.2.RELEASE/javadoc-api/org/springframework/beans/BeanUtils.html

于 2020-05-29T09:33:01.477 回答
-2

针对@Ashish Chaurasia 提供的答案,想提一下解决方案是部分的。该类ApplicationContextUtils也应该是一个 spring bean,以便 spring 调用下面的代码。

if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(ctx); 
}

@Component在类的顶部将使解决方案完整。此外,还有另一种使用@Autowired注释的方法。

@Component
public class ApplicationContextProvider {
    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    @Autowired
    public void setContext(ApplicationContext context) {
        ApplicationContextProvider.context = context;
    }
}

getBean现在可以通过以下方式轻松访问该方法 -

ApplicationContextProvider.getApplicationContext().getBean("myBean");

于 2019-08-21T17:43:53.807 回答