[英]Spring - using factory beans in configuration?
What is the correct way to use factory beans in @Configuration
classes? 在
@Configuration
类中使用工厂bean的正确方法是什么?
Suppose I have the following for SessionFactory
: 假设我有以下
SessionFactory
:
@Bean
public AnnotationSessionFactoryBean sessionFactory() {
AnnotationSessionFactoryBean factory = new AnnotationSessionFactoryBean();
// set up properties etc.
return factory;
}
Right now this method returns a bean factory which does not implement SessionFactory
. 现在这个方法返回一个没有实现
SessionFactory
的bean工厂。 If I use it in another bean with @Autowired
as SessionFactory
, it works just fine and obtains it from bean factory: 如果我在另一个使用
@Autowired
作为SessionFactory
bean中使用它,它可以正常工作并从bean工厂获取它:
@Controller
public class MyController {
@Autowired SessionFactory sessionFactory;
// ...
}
I guess that's OK. 我想那没关系。
However, it becomes an issue if I want to use the SessionFactory
in the same configuration class: 但是,如果我想在同一个配置类中使用
SessionFactory
,它就成了一个问题:
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager man = new HibernateTransactionManager();
// Ideal - doesn't work because sessionFactory() return type doesn't match:
// SessionFactory sessionFactory = sessionFactory();
// Is this one correct?
// SessionFactory sessionFactory = (SessionFactory) sessionFactory().getObject();
man.setSessionFactory(sessionFactory);
return man;
}
What is The Right Way to implement this kind of dependency? 实现这种依赖的正确方法是什么?
@Configuration
approach is still relatively fresh and it has some rough edges. @Configuration
方法仍然相对新鲜,它有一些粗糙的边缘。 Factory beans are one of them. 工厂豆是其中之一。 So the is no Right Way , at least I am not aware of any.
所以没有正确的方法 ,至少我不知道。 Maybe future Spring releases will handles this case somehow.
也许未来的Spring版本会以某种方式处理这个案例。 For now, this is my preferred way:
现在,这是我的首选方式:
@Bean
public AnnotationSessionFactoryBean sessionFactoryBean() {
AnnotationSessionFactoryBean factory = new AnnotationSessionFactoryBean();
// set up properties etc.
return factory;
}
@Bean
public SessionFactory sessionFactory() {
return (SessionFactory) sessionFactoryBean().getObject();
}
And use sessionFactory()
method whenever needed. 并在需要时使用
sessionFactory()
方法。 If you want to call the sessionFactoryBean().getObject()
several times for some reason (eg when FactoryBean
does not return singletons), remember to use @Scope
annotation. 如果由于某种原因想要多次调用
sessionFactoryBean().getObject()
(例如,当FactoryBean
不返回单例时),请记住使用@Scope
注释。 Otherwise Spring will make sure sessionFactory()
is called only once and cache the result. 否则,Spring将确保仅调用
sessionFactory()
一次并缓存结果。
Spring is intelligent enough to perform all required initialization after calling @Bean
method and before returning the bean itself. Spring足够智能,可以在调用
@Bean
方法之后和返回bean本身之前执行所有必需的初始化。 So InitializingBean
, DisposableBean
, @PostConstruct
, etc. are all recognized and treated properly. 所以
InitializingBean
, DisposableBean
,@ @PostConstruct
等都被正确识别和处理。 In fact, I was always finding calling afterPropertiesSet
a bit of a hack, because it is the container responsibility. 事实上,我总是发现调用
afterPropertiesSet
有点黑客,因为它是容器的责任。
Also there is a second method advised in Spring Datastore Document - Reference Documentation , which at first sight looks a bit inconsistent, but works great: 另外,在Spring数据存储文档 - 参考文档中建议了第二种方法,乍一看看起来有些不一致,但效果很好:
@Resource
private Mongo mongo;
@Bean
MongoFactoryBean mongo() {
return new MongoFactoryBean();
}
So factory is created using @Bean
method but the bean created by the factory can be obtained using autowired field. 因此,工厂是使用
@Bean
方法创建的,但工厂创建的bean可以使用自动装配字段获取。 Clever. 聪明。
You can use it the following way: 您可以通过以下方式使用它:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class LoginServiceTest {
@Configuration
public static class Config {
@Bean
public HttpInvokerProxyFactoryBean loginServiceProxy() {
HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
proxy.setServiceInterface(LoginService.class);
proxy.setServiceUrl("http://localhost:8080/loginService");
return proxy;
}
}
@Inject
private LoginService loginService;
@Test
public void testlogin() {
loginService.login(...);
}
}
I found an example of this on the Spring forums . 我在Spring论坛上找到了一个这样的例子。
@Bean
public SessionFactory sessionFactory() {
AnnotationSessionFactoryBean sessionFactoryBean =
new AnnotationSessionFactoryBean();
// ...configuration code here...
sessionFactoryBean.afterPropertiesSet();
return sessionFactoryBean.getObject();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.