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

And*_*ate 24 java spring inversion-of-control spring-annotations

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

但是,在Spring 3.0中,我找不到一种令人满意的方法来使用带有基于注释的配置的工厂bean(néeJavaConfig).

显然,我可以手动实例化工厂bean并自己设置任何所需的属性,如下所示:

@Configuration
public class AppConfig {

...

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource());
        factory.setAnotherProperty(anotherProperty());

        return factory.getObject();
    }
Run Code Online (Sandbox Code Playgroud)

然而,如果这将无法FactoryBean实现任何Spring特有的回调接口,如InitializingBean,ApplicationContextAware,BeanClassLoaderAware,或@PostConstruct例如.我还需要通过调用来检查的FactoryBean,找出回调接口它实现了,那么实现这个功能我自己setApplicationContext,afterPropertiesSet()等等.

这对我来说感觉很尴尬和反过来:应用程序开发人员不应该实现IOC容器的回调.

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

tsa*_*hev 22

我认为,当您依赖自动布线时,这是最好的解决方案.如果您对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);
}
Run Code Online (Sandbox Code Playgroud)

所以Spring将为我们注入myFactory().getObject()返回的MyBean实例,就像它配置XML一样.

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


axt*_*avt 21

据我理解你的问题是你想要的结果sqlSessionFactory()是一个SqlSessionFactory(在其他方法使用),但你必须返回SqlSessionFactoryBean@Bean-annotated方法,以触发弹簧回调.

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

@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());
    }
}
Run Code Online (Sandbox Code Playgroud)

关键是对@Bean-annotated方法的调用被一个方面截获,该方面执行返回的bean的初始化(FactoryBean在你的情况下),以便调用sqlSessionFactoryBean()in sqlSessionFactory()返回一个完全初始化的FactoryBean.


obj*_*cts 5

Spring JavaConfig有一个ConfigurationSupport类,它有一个与FactoryBean一起使用的getObject()方法.

你会用它来扩展

@Configuration
public class MyConfig extends ConfigurationSupport {

    @Bean
    public MyBean getMyBean() {
       MyFactoryBean factory = new MyFactoryBean();
       return (MyBean) getObject(factory);
    }
}
Run Code Online (Sandbox Code Playgroud)

这个jira问题有一些背景知识

在Spring 3.0中,JavaConfig被转移到Spring核心,并决定摆脱ConfigurationSupport类.建议的方法是现在使用构建器模式而不是工厂.

从新的SessionFactoryBuilder中获取的示例

@Configuration
public class DataConfig {
    @Bean
    public SessionFactory sessionFactory() {
        return new SessionFactoryBean()
           .setDataSource(dataSource())
           .setMappingLocations("classpath:com/myco/*.hbm.xml"})
           .buildSessionFactory();
    }
}
Run Code Online (Sandbox Code Playgroud)

一些背景在这里