java Spring - 在配置中使用工厂 bean?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6446857/
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 - using factory beans in configuration?
提问by Konrad Garus
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
. If I use it in another bean with @Autowired
as SessionFactory
, it works just fine and obtains it from bean factory:
现在这个方法返回一个没有实现的 bean 工厂SessionFactory
。如果我在另一个带有@Autowired
as 的bean 中使用它SessionFactory
,它就可以正常工作并从 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?
实现这种依赖的正确方法是什么?
回答by Tomasz Nurkiewicz
@Configuration
approach is still relatively fresh and it has some rough edges. 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. For now, this is my preferred way:
@Configuration
方法还是比较新鲜的,有一些粗糙的地方。工厂豆就是其中之一。所以没有正确的方法,至少我不知道。也许未来的 Spring 版本会以某种方式处理这种情况。目前,这是我的首选方式:
@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. If you want to call the sessionFactoryBean().getObject()
several times for some reason (e.g. when FactoryBean
does not return singletons), remember to use @Scope
annotation. Otherwise Spring will make sure sessionFactory()
is called only once and cache the result.
并sessionFactory()
在需要时使用方法。如果你sessionFactoryBean().getObject()
因为某种原因想要多次调用(例如 whenFactoryBean
不返回单例),记得使用@Scope
注解。否则 Spring 将确保sessionFactory()
只调用一次并缓存结果。
Spring is intelligent enough to perform all required initialization after calling @Bean
method and before returning the bean itself. So InitializingBean
, DisposableBean
, @PostConstruct
, etc. are all recognized and treated properly. In fact, I was always finding calling afterPropertiesSet
a bit of a hack, because it is the container responsibility.
Spring 足够智能,可以在调用@Bean
方法之后和返回 bean 本身之前执行所有必需的初始化。因此InitializingBean
,DisposableBean
、@PostConstruct
、 等都被正确识别和处理。事实上,我一直觉得调用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 Datastore Document - Reference Documentation 中还建议了第二种方法,乍一看有点不一致,但效果很好:
@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. Clever.
所以工厂是使用@Bean
方法创建的,但是工厂创建的 bean 可以使用自动装配字段获得。聪明的。
回答by Mark McLaren
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();
}
回答by Ortwin Angermeier
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(...);
}
}