弹簧自动装配在非弹簧管理类中不起作用
Posted
技术标签:
【中文标题】弹簧自动装配在非弹簧管理类中不起作用【英文标题】:spring autowiring not working from a non-spring managed class 【发布时间】:2013-08-23 05:45:50 【问题描述】:我有一个通过调用构造函数来实例化的类(ABC 类)。 ABC 类又具有一个使用自动连线注入的辅助类(XYZ 类)。
我们的是基于 Spring MVC 的应用程序,在服务器启动时我没有看到任何异常。
但我仍然看到 XYZ 类为空。是不是因为Class ABC没有被Spring Container实例化?
在这种情况下,如何使用自动接线?
谢谢。
【问题讨论】:
我确信你不能自动装配不受 Spring 管理的 bean。你需要通过其他方式获取 XYZ 实例的引用。如果是 Helper 类,则将 XYZ 的方法设为静态并使用类名使用它们。我就是这么做的。 请参考github.com/ahmedbhaila/non-managed-beans,我试过了,效果很好。 【参考方案1】:你可以通过这种方式在非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);
【讨论】:
如何设置appContext? Spring 容器将注入该对象。 就我而言,我需要在ApplicationContextUtils
上添加@Component
,或者只在ApplicationContextUtils .getApplicationContext();
期间获得null
很棒的解决方案!【参考方案2】:
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
【讨论】:
请注意,这些方法使用其无参数构造函数实例化一个类。如果没有找到主要/默认构造函数,您可以获得 BeanInstantiationException。【参考方案3】:针对@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");
【讨论】:
【参考方案4】:对于像我这样使用基本 Spring Boot 并且不熟悉术语的新手:
您的服务、存储库等都是 Bean 您可以从 ApplicationContext 获取您的 BeansAshish 的 answer 对我有用,但 this article 提供了更多解释。
如果您不知道想要的 bean 的名称,请尝试在此数组中查找:
String[] names = context.getBeanDefinitionNames();
如果您对“组件扫描”和配置文件的讨论感到困惑,了解@SpringBootApplication 注解(您可能会在 main() 方法附近找到)隐式调用 @Configuration 和 @ComponentScan 可能会有所帮助。
这意味着该包中的所有文件(在主类顶部声明)都由 Spring 拾取,并且您要添加的任何 bean 都可以与 main() 一起编写
【讨论】:
【参考方案5】:您可以在要自动装配其他 bean 的类中使用 Spring 的 @Configurable 注解。 此外,您需要使用 @EnableSpringConfigured 注释任何配置 bean,以便 Spring 知道您的可配置 bean。
@EnableSpringConfigured documentation
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
...
【讨论】:
嗨 ibai,MyClass 是干什么用的?它也是一个非弹簧管理对象。我们可以在 Application 类中新建 ABC() 吗?谢谢。【参考方案6】:您可以使用@Configurable
注释来注释ABC
类。然后 Spring IOC 会将XYZ
实例注入ABC
类。它通常与 AspectJ AnnotationBeanConfigurerAspect
一起使用。
【讨论】:
【参考方案7】:第一个问题 - 是的,你有 null 因为类不是用 spring 启动的 第二个问题-我认为您可以使用 aspectj 支持http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-using-aspectj
【讨论】:
【参考方案8】:自动装配不起作用,因为 ABC 类不是由 Spring 管理的。您可以通过使用类定义上方的@Component 注释(@Component、@Service、@Controller 等)之一,然后在应用程序上下文 XML 中使用 context:component-scan 来让 Spring 管理 ABC,或者去老学校和只需在应用程序上下文中直接定义 bean。
如果由于某种原因你不能让 Spring 管理 ABC 类,你可以使用类似的方式在 ABC 中加载应用程序上下文:
ApplicationContext 上下文 = 新 ClassPathXmlApplicationContext("path/to/applicationContext.xml");
然后使用:
XYZ someXyz = (XYZ) context.getBean("MyXYZ");
手动设置 bean 值。
【讨论】:
【参考方案9】:简而言之,是的,ABC 没有被注入 XYZ,因为 Spring 没有管理 ABC。 Spring 无法配置它不知道的对象。
您可以通过使用@Service
或@Component
注释来管理ABC。请注意,为了让 Spring 接收这些注释,Spring 必须打开自动扫描:
<context:component-scan base-package="com.mypackage.awesomeproject" />
【讨论】:
【参考方案10】:正确:你不能只在课堂上调用new
并把它全部连接起来; Spring 必须管理 bean 才能发挥所有魔力。
如果您可以发布有关您的用例的更多详细信息,我们或许可以建议有用的选项。
【讨论】:
docs.spring.io/spring-framework/docs/current/javadoc-api/org/…以上是关于弹簧自动装配在非弹簧管理类中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
尺寸检查器的自动调整大小掩码中的支柱和弹簧似乎在 iOS5 模拟器中不起作用 [关闭]
自动装配在 Apache Shiro 自定义领域类中不起作用