我的春天依赖项工作正常,但有一个类
CustomUserDetaisls
我需要名为
@Autowired Private UserDAO userDAO
与用户名和密码匹配
但是我的弹簧注入不起作用,因为这个类实现了userDetailsSerivce
。但是,如果我删除了工具,则注入工作。
我已经在this question提交了问题,但是没有人给我回答,所以我决定将DAO与新操作员一起使用
private UserDAO userDAO = new UserDAO();
但userDAO
依赖于会话工厂,它是一个春天豆。
然后我再次决定从java代码获取sessionfactory,而不是使用以下代码
SessionFactory sessionFactory = new AnnotationConfiguration()
.configure("com/vaannila/service/hibernate.cfg.xml")
.buildSessionFactory();
但我再次在hibernate-context中有几个bean,比如datasource,properties文件,我发现很难重写所有的东西。
有什么方法可以手动注入userDAO
,以便所有相关的弹簧注入像sessionFactories一样
答案 0 :(得分:5)
如果您有权访问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要求在它可以使用之前自动装配,我更喜欢使用第一个机制并将构造函数标记为private / protected,以确保它不能通过'new'创建并强制它通过上面的工厂创建。
更新11/27/17
我个人不想每次想要创建自动装配的实例时都使用工厂。特别是如果某个其他进程正在创建实例,例如从数据库反序列化等等
我最终创建了一个方面来自动处理自动装配。
首先,我创建了一个注释来标记我想要自动自动装配的类:
@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();
更新1/2/2018
接口ApplicationContext已更改,并且get()已被删除,但您仍然可以使用第一种机制,但您需要调用getAutowireCapableBeanFactory()。
因此,此答案顶部示例中的前两行现在看起来像:
ApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
AutowireCapableBeanFactory factory = springContext.getAutowireCapableBeanFactory();
答案 1 :(得分:2)
你可以看一下spring java配置。 http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java
在下面的示例中,UserDAO的所有依赖项将由spring自动设置。 它应该是这样的:
@Configuration
@PropertySource("classpath:configuration.properties")
public class ApplicationConfig {
@Bean
public UserDAO userDAO() {
return new UserDAO();
}
@Bean
public CustomUserDetails customUserDetails (UserDAO userDAO) {
CustomUserDetails customUserDetails = new CustomUserDetails ();
customUserDetails.setUserDAO(userDAO());
return customUserDetails;
}
}