我有一个通过调用构造函数来实例化的类(ABC 类)。ABC 类又具有一个使用自动连线注入的辅助类(XYZ 类)。
我们是一个基于 Spring MVC 的应用程序,在服务器启动时我没有看到任何异常。
但我仍然看到 XYZ 类为空。是不是因为 Class ABC 没有被 Spring Container 实例化?
在这种情况下,我如何使用自动接线?
谢谢。
我有一个通过调用构造函数来实例化的类(ABC 类)。ABC 类又具有一个使用自动连线注入的辅助类(XYZ 类)。
我们是一个基于 Spring MVC 的应用程序,在服务器启动时我没有看到任何异常。
但我仍然看到 XYZ 类为空。是不是因为 Class ABC 没有被 Spring Container 实例化?
在这种情况下,我如何使用自动接线?
谢谢。
您可以使用这种方式在非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);
自动装配不起作用,因为 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 值。
正确:你不能只叫new
一个班级然后把它全部连接起来;Spring 必须管理 bean 才能发挥其所有魔力。
如果您可以发布有关您的用例的更多详细信息,我们可能会建议有用的选项。
您可以在要自动装配其他 bean 的类中使用 Spring 的 @Configurable 注释。此外,您需要使用 @EnableSpringConfigured 注释任何配置 bean,以便 Spring 知道您的可配置 bean。
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
...
}
}
对于像我这样做基本 Spring Boot 并且不熟悉术语的菜鸟:
如果您不知道所需 bean 的名称,请尝试查看此数组:
String[] names = context.getBeanDefinitionNames();
如果您对“组件扫描”和配置文件的讨论感到困惑,那么了解@SpringBootApplication 注解(您可能会在 main() 方法附近找到)隐式调用 @Configuration 和 @ComponentScan 可能会有所帮助。
这意味着该包中的所有文件(在主类顶部声明)都由 Spring 拾取,并且您想要添加的任何 bean 都可以与 main() 一起编写
简而言之,是的,ABC 没有被注入 XYZ,因为 Spring 没有管理 ABC。Spring 无法配置它不知道的对象。
您可以通过使用@Service
或注释来管理 ABC @Component
。请注意,为了让 Spring 接收这些注释,Spring 必须打开自动扫描:
<context:component-scan base-package="com.mypackage.awesomeproject" />
第一个问题 - 是的你有 null 因为类不是用 spring 启动的第二个问题 - 我认为你可以使用 aspectj 支持http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop .html#aop-using-aspectj
您可以使用注释ABC
对类进行@Configurable
注释。XYZ
然后 Spring IOC 会将实例注入到ABC
类中。它通常与 AspectJ 一起使用AnnotationBeanConfigurerAspect
。
Spring 有 util 类
BeanUtils.instantiateClass(clazz)
BeanUtils.instantiate(clazz)
YouClass ins = BeanUtils.instantiate(YouClass.class)
针对@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");