FactoryBeans 和 Spring 3.0 中基于注释的配置

Spring提供了允许对Bean进行非平凡初始化的接口。该框架提供了许多工厂bean的实现,并且 - 当使用Spring的XML配置时 - 工厂bean易于使用。FactoryBean

但是,在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();
    }

但是,如果实现了任何特定于Spring的回调接口,例如,,,或,这将失败。我还需要检查FactoryBean,找出它实现的回调接口,然后通过调用等方式自己实现此功能。FactoryBeanInitializingBeanApplicationContextAwareBeanClassLoaderAware@PostConstructsetApplicationContextafterPropertiesSet()

这对我来说很尴尬和背对头:应用程序开发人员不应该实现IOC容器的回调。

有谁知道使用Spring Annotation配置的FactoryBeans的更好解决方案吗?


答案 1

我认为,当您依靠自动布线时,这是最好的解决方案。如果您对 Bean 使用 Java 配置,则如下所示:

@Bean
MyFactoryBean myFactory()
{ 
    // this is a spring FactoryBean for MyBean
    // i.e. something that implements FactoryBean<MyBean>
    return new MyFactoryBean();
}

@Bean
MyOtherBean myOther(final MyBean myBean)
{
    return new MyOtherBean(myBean);
}

因此,Spring将为我们注入由myFactory().getObject()返回的MyBean实例,就像XML配置一样。

如果您在@Component/@Service等类中使用@Inject/@Autowire,这也应该有效。


答案 2

据我所知,您的问题是您希望结果是什么(用于其他方法),但是您必须从-annotated方法返回才能触发Spring回调。sqlSessionFactory()SqlSessionFactorySqlSessionFactoryBean@Bean

可以通过以下解决方法解决:

@Configuration 
public class AppConfig { 
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactoryBean sqlSessionFactoryBean() { ... }

    // FactoryBean is hidden behind this method
    public SqlSessionFactory sqlSessionFactory() {
        try {
            return sqlSessionFactoryBean().getObject();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    @Bean
    public AnotherBean anotherBean() {
        return new AnotherBean(sqlSessionFactory());
    }
}

关键是,对 -annotated 方法的调用被一个方面截获,该方面执行返回的 bean 的初始化(在你的例子中),因此对 in 的调用将返回一个完全初始化的 。@BeanFactoryBeansqlSessionFactoryBean()sqlSessionFactory()FactoryBean


推荐