如果您可以访问 spring 上下文,则可以检索 AutowireCapableBeanFactory,然后您可以将其用于任何 bean,如下所示:
ApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
AutowireCapableBeanFactory factory = springContext.get(AutowireCapableBeanFactory.class);
// this would instantiate and autowire a bean:
UserDAO userDAO = factory.createBean(UserDAO.class);
// this will autowire an already existing bean:
UserDAO manualUserDAO = new UserDAO();
factory.initializeBean(manualUserDAO, "beanNameIfNeeded");
但是,如果 bean 需要在使用之前自动装配,我更喜欢使用第一种机制并将构造函数标记为私有/受保护,以确保它不能通过“new”创建并强制它通过像上面这样的工厂创建。
2017 年 11 月 27 日更新
我个人不喜欢每次想创建自动装配实例时都必须使用工厂。特别是如果其他进程正在创建实例,例如从数据库反序列化等。
我最终创建了一个方面来自动处理自动装配。
首先,我创建了一个注释来标记我希望自动装配的类:
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface AutowireAfterCreation {
}
然后我创建了一个使用“构造后”切点进行自动装配的方面。不幸的是,我无法找出仅在“最后一个”构造函数完成后才调用的切入点,但至少在我的情况下,多次自动装配似乎并没有什么坏处。
public aspect AutowiringAfterCreation {
@Autowired
private AutowireCapableBeanFactory beanFactory;
/**
* After construction, autowire the instance.
* @param o Newly created object to be autowired.
*/
after(Object o) returning : target(o) && initialization((@AutowireAfterCreation *).new(..)) {
// this aspect will actually autowire the instance multiple times if the class is part of an inheritance
// Hierarchy. This is not optimal, but it should not hurt anything to autowire more than once.
// FUTURE: modify the aspect so it only runs once, regardless of how many constructor calls are necessary.
beanFactory.autowireBeanProperties(o, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
beanFactory.initializeBean(o, "unused");
}
}
然后我必须告诉 Spring 关于方面的信息,以便 factoryBean 自动装配到方面本身:
<bean class="AutowiringOnDemand" factory-method="aspectOf"/>
现在我可以创建任何实例,只需附加注释即可自动自动装配:
@AutowireAfterCreation
public class TestEntity {
@Value("${some.config.value}")
private String value;
@Autowired
private TestRepository repository;
}
最后,你要做的就是创建一个实例,它在构造函数完成后自动自动装配:
TestEntity entity = new TestEntity();
2018 年 1 月 2 日更新
接口ApplicationContext发生了变化,去掉了get(),但是仍然可以使用第一种机制,但是需要调用getAutowireCapableBeanFactory()代替。
因此,该答案顶部示例中的前两行现在看起来像:
ApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
AutowireCapableBeanFactory factory = springContext.getAutowireCapableBeanFactory();