spring 自动装配在非 spring 托管类中不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18347518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
spring autowiring not working from a non-spring managed class
提问by l a s
I have a class (Class ABC) that's instantiated by calling the constructor. Class ABC in turn has a helper class (Class XYZ) injected using auto-wired.
我有一个通过调用构造函数实例化的类(类 ABC)。ABC 类又具有使用自动连线注入的辅助类(XYZ 类)。
Ours is a Spring MVC based application and I don't see any exception while server start-up.
我们是一个基于 Spring MVC 的应用程序,在服务器启动时我没有看到任何异常。
But I still see Class XYZ coming as null. Is it because of the fact that Class ABC is not instantiated by Spring Container?
但我仍然看到 XYZ 类为空。是不是因为Spring Container没有实例化ABC类?
In such scenarios, how do i make use of auto-wiring?
在这种情况下,如何使用自动布线?
Thanks.
谢谢。
回答by Ashish Chaurasia
You can use this way to use spring bean in non-spring bean class
可以通过这种方式在非spring bean类中使用spring bean
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
}
now you can get the applicationcontext object by getApplicationContext() this method.
现在你可以通过 getApplicationContext() 这个方法来获取 applicationcontext 对象。
from applicationcontext you can get spring bean objects like this:
从 applicationcontext 你可以得到这样的 spring bean 对象:
ApplicationContext appCtx = ApplicationContextUtils
.getApplicationContext();
String strFromContext = (String) appCtx.getBean(beanName);
回答by lreeder
Autowiring won't work because class ABC is not managed by Spring. You could make Spring manage ABC by using one of the @Component annotations (@Component, @Service, @Controller, etc) above the class definition, and then using context:component-scan in your application context XML, or go old school and just define the bean directly in your application context.
自动装配将不起作用,因为 ABC 类不是由 Spring 管理的。您可以通过使用类定义上方的@Component 注释(@Component、@Service、@Controller 等)之一,然后在应用程序上下文 XML 中使用 context:component-scan 来让 Spring 管理 ABC,或者去老派和只需直接在您的应用程序上下文中定义 bean。
If for some reason you can't make Spring manage class ABC, you can load the application context in ABC using something like:
如果由于某种原因您不能让 Spring 管理类 ABC,您可以使用以下内容在 ABC 中加载应用程序上下文:
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
and then use:
然后使用:
XYZ someXyz = (XYZ) context.getBean("MyXYZ");
XYZ someXyz = (XYZ) context.getBean("MyXYZ");
to manually set the bean value.
手动设置 bean 值。
回答by chrylis -cautiouslyoptimistic-
Correct: You can't just call newon a class and get it all wired up; Spring has to be managing the bean for it to do all of its magic.
正确:你不能只是打电话new给一个班级并把它全部连接起来;Spring 必须管理 bean 才能发挥其所有魔力。
If you can post more details on your use case, we may be able to suggest useful options.
如果您可以发布有关您的用例的更多详细信息,我们可能会建议有用的选项。
回答by ibai
You can use Spring's @Configurable annotation in the class you want to autowire other beans. Additionally, you will need to annotate any configuration bean with @EnableSpringConfigured so that Spring is aware of your configurable beans.
您可以在要自动装配其他 bean 的类中使用 Spring 的 @Configurable 注释。此外,您需要使用 @EnableSpringConfigured 注释任何配置 bean,以便 Spring 知道您的可配置 bean。
@EnableSpringConfigured documentation
public @interface EnableSpringConfigured Signals the current application context to apply dependency injection to non-managed classes that are instantiated outside of the Spring bean factory (typically classes annotated with the @Configurable annotation). Similar to functionality found in Spring's XML element. Often used in conjunction with @EnableLoadTimeWeaving.
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
...
}
}
回答by Louis
For noobs like me who do basic Spring Boot and aren't familiar with the lingo:
对于像我这样使用基本 Spring Boot 并且不熟悉术语的菜鸟:
- Your Services, Repos etc are all Beans
- You can get your Beans from the ApplicationContext
- 你的服务、回购等都是 Beans
- 你可以从 ApplicationContext 中获取你的 Beans
Ashish's answerworks for me, but this articleprovides a bit more explanation imo.
If you don't know the name of the bean you want, try looking in this array:
如果您不知道所需 bean 的名称,请尝试在此数组中查找:
String[] names = context.getBeanDefinitionNames();
If you're confused by the talk of 'component scan' and config files, it may help to know that the @SpringBootApplication annotation (which you might find near your main() method) implicitly calls @Configuration and @ComponentScan.
如果您对“组件扫描”和配置文件的讨论感到困惑,那么了解 @SpringBootApplication 注释(您可能会在 main() 方法附近找到)隐式调用 @Configuration 和 @ComponentScan 可能会有所帮助。
This means all files in that package (declared at the top of the main class) are picked up by Spring, and any beans you want to add can be written alongside main()
这意味着该包中的所有文件(在主类的顶部声明)都由 Spring 获取,并且您想要添加的任何 bean 都可以与 main() 一起编写
回答by bstempi
In short, yes, ABC is not getting injected with XYZ because Spring is not managing ABC. Spring can't configure objects that it doesn't know about.
简而言之,是的,ABC 没有被注入 XYZ,因为 Spring 没有管理 ABC。Spring 无法配置它不知道的对象。
You could manage ABC by annotating it with @Serviceor @Component. Note that in order for Spring to pick up on these annotations, Spring must have auto-scanning turned on:
您可以通过使用@Service或注释来管理 ABC @Component。请注意,为了让 Spring 接收这些注释,Spring 必须打开自动扫描:
<context:component-scan base-package="com.mypackage.awesomeproject" />
回答by Alexander Kudrevatykh
First question - yes you have null because class not initiated with spring Second question - I think you can use aspectj support http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-using-aspectj
第一个问题 - 是的你有空,因为类不是用 spring 第二个问题 - 我认为你可以使用 aspectj 支持http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop .html#aop-using-aspectj
回答by michal.kreuzman
You can annotate ABCclass with @Configurableannotation. Then Spring IOC will inject XYZinstance to ABCclass. It's typically used with the AspectJ AnnotationBeanConfigurerAspect.
您可以使用注释对ABC类进行@Configurable注释。然后 Spring IOC 会将XYZ实例注入到ABC类中。它通常与 AspectJ 一起使用AnnotationBeanConfigurerAspect。
回答by kuhajeyan
Spring has util class
Spring 有 util 类
BeanUtils.instantiateClass(clazz)
BeanUtils.instantiate(clazz)
YouClass ins = BeanUtils.instantiate(YouClass.class)
回答by Neetesh Dadwariya
In response to the answer provided by @Ashish Chaurasia, would like to mention that the solution is partial. The class ApplicationContextUtilsshould also be a spring bean in order for spring to invoke the below code.
针对@Ashish Chaurasia 提供的答案,想提一下解决方案是部分的。该类ApplicationContextUtils也应该是一个 spring bean,以便 spring 调用以下代码。
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(ctx);
}
@Componentat the top of the class would make the solution complete. Also, there is one more alternative of doing it with the @Autowiredannotation.
@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;
}
}
The getBeanmethod can now easily be accessed by -
getBean现在可以通过以下方式轻松访问该方法 -
ApplicationContextProvider.getApplicationContext().getBean("myBean");
ApplicationContextProvider.getApplicationContext().getBean("myBean");

