Spring 3.0中FactoryBeans和基于注解的配置
Spring 提供了FactoryBean 接口来允许对bean 进行重要的初始化。该框架提供了工厂 bean 的许多实现,并且当使用 Spring 的 XML 配置时,工厂 bean 很容易使用。
然而,在 Spring 3.0 中,我找不到一种令人满意的方法来使用工厂 bean 和基于注释的配置(née JavaConfig)。
显然,我可以手动实例化工厂 bean 并自己设置任何必需的属性,如下所示:
@Configuration
public class AppConfig {
...
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource());
factory.setAnotherProperty(anotherProperty());
return factory.getObject();
}
但是,如果 FactoryBean
实现了任何 Spring 特定的回调接口,例如 InitializingBean
,这将会失败>、ApplicationContextAware
、BeanClassLoaderAware
或 @PostConstruct
例如。我还需要检查 FactoryBean,找出它实现的回调接口,然后通过调用 setApplicationContext、afterPropertiesSet() 等来自己实现此功能。
这感觉很尴尬和后退 -对我来说,应用程序开发人员不必实现 IOC 容器的回调。
有谁知道从 Spring Annotation 配置中使用 FactoryBeans 的更好解决方案?
Spring provides the FactoryBean
interface to allow non-trivial initialisation of beans. The framework provides many implementations of factory beans and -- when using Spring's XML config -- factory beans are easy to use.
However, in Spring 3.0, I can't find a satisfactory way of using factory beans with the annotation-based configuration (née JavaConfig).
Obviously, I could manually instantiate the factory bean and set any required properties myself, like so:
@Configuration
public class AppConfig {
...
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource());
factory.setAnotherProperty(anotherProperty());
return factory.getObject();
}
However, this would fail if the FactoryBean
implemented any Spring-specific callback interfaces, like InitializingBean
, ApplicationContextAware
, BeanClassLoaderAware
, or @PostConstruct
for example. I also need to inspect the FactoryBean, find out what callback interfaces it implements, then implement this functionality myself by calling setApplicationContext
, afterPropertiesSet()
etc.
This feels awkward and back-to-front to me: application-developers should not have to implement the callbacks of the IOC container.
Does anyone know of a better solution to using FactoryBeans from Spring Annotation configs?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我认为当您依靠自动装配时最好解决这个问题。如果您对 bean 使用 Java 配置,则如下所示:
因此 Spring 将为我们注入由 myFactory().getObject() 返回的 MyBean 实例,就像使用 XML 配置一样。
如果您在 @Component/@Service 等类中使用 @Inject/@Autowire ,这也应该有效。
I think that this is best solved when you rely on auto-wiring. If you are using Java configuration for the beans, this would like:
So Spring will inject for us the MyBean instance returned by the myFactory().getObject() as it does with XML configuration.
This should also work if you are using @Inject/@Autowire in your @Component/@Service etc classes.
据我了解,您的问题是您希望
sqlSessionFactory()
的结果成为SqlSessionFactory
(用于其他方法),但您必须返回SqlSessionFactoryBean
来自@Bean
注解的方法,以触发 Spring 回调。可以通过以下解决方法来解决这个问题:
重点是,对 @Bean 注释方法的调用会被执行返回 bean 初始化的方面拦截(
FactoryBean
in您的情况),以便在sqlSessionFactory()
中调用sqlSessionFactoryBean()
返回完全初始化的FactoryBean
。As far as I understand your problem is what you want a result of
sqlSessionFactory()
to be aSqlSessionFactory
(for use in other methods), but you have to returnSqlSessionFactoryBean
from a@Bean
-annotated method in order to trigger Spring callbacks.It can be solved with the following workaround:
The point is that calls to
@Bean
-annotated methods are intercepted by an aspect which performs initialization of the beans being returned (FactoryBean
in your case), so that call tosqlSessionFactoryBean()
insqlSessionFactory()
returns a fully initializedFactoryBean
.Spring JavaConfig 有一个 ConfigurationSupport 类,具有与 FactoryBean 一起使用的 getObject() 方法。
你可以使用它来扩展
jira问题有一些背景
,Spring 3.0 JavaConfig是移入 Spring 核心,并决定摆脱 ConfigurationSupport 类。建议的方法是现在使用构建器模式而不是工厂。
取自新的 SessionFactoryBuilder
一些背景此处
Spring JavaConfig had a ConfigurationSupport class that had a getObject() method for use with FactoryBean's.
You would use it be extending
There is some background in this jira issue
With Spring 3.0 JavaConfig was moved into Spring core and it was decided to get rid of the ConfigurationSupport class. Suggested approach is to now use builder pattern instead of factories.
An example taken from the new SessionFactoryBuilder
Some background here
这就是我正在做的事情,并且它有效:
您声明的任何 bean 都可以作为参数传递给任何其他 @Bean 方法(再次调用相同的方法将创建一个不被 spring 处理的新实例)。
如果声明一个 FactoryBean,则可以使用它创建的 bean 类型作为另一个 @Bean 方法的参数,并且它将接收正确的实例。
您也可以使用
Anywhere,它也会起作用。
This is what I'm doing, and it works:
Any bean you have declared can be passed as an argument to any other @Bean method (invoking the same method again will create a new instance which is not processed by spring).
If you declare a FactoryBean, you can use the bean type it creates as an argument for another @Bean method, and it will receive the right instance.
You could also use
Anywhere and it will work too.
为什么不在 AppConfiguration 中注入 Factory?
但是我可能没有正确理解你的问题。因为在我看来,你正在尝试一些奇怪的事情 - 退后一步,重新思考你真正需要什么。
Why do you not inject the Factory in your AppConfiguration?
But may I did not understand your question correct. Because it looks to me that you are trying something strange - go a step back and rethink what are you really need.
我是这样做的:
sessionFactoryBean 被创建,并且正确的创建后生命周期的事情发生在它上面(afterPropertiesSet 等)。
请注意,我没有直接将 sessionFactoryBean 引用为 bean。我将 sessionFactory 自动连接到我的其他 bean 中。
Here is how I am doing it:
The sessionFactoryBean gets created and the proper post-create lifecycle stuff happens to it (afterPropertiesSet, etc).
Note that I do not reference the sessionFactoryBean as a bean directly. I autowire the sessionFactory into my other beans.