SpringはFactoryBean
インターフェースを提供して、豆の重要な初期化を可能にします。フレームワークは、ファクトリBeanの多くの実装を提供し、SpringのXML構成を使用すると、ファクトリBeanは使いやすくなります。
しかし、Spring 3.0では、アノテーションベースの構成(néeJavaConfig)でファクトリーBeanを使用する満足のいく方法を見つけることができません。
明らかに、手動でファクトリー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
が、InitializingBean
、ApplicationContextAware
、BeanClassLoaderAware
、または_@PostConstruct
_ for_例。また、FactoryBeanを検査し、それが実装するコールバックインターフェースを見つけ、setApplicationContext
、afterPropertiesSet()
などを呼び出してこの機能を自分で実装する必要があります。
これは、私にとってはぎこちなく前向きです。アプリケーション開発者は、IOCコンテナのコールバックを実装する必要はありません。
Spring Annotationの構成からFactoryBeanを使用するためのより良いソリューションを知っている人はいますか?
私が理解している限り、あなたの問題はsqlSessionFactory()
の結果をSqlSessionFactory
(他のメソッドで使用するため)にしたいものですが、SqlSessionFactoryBean
を返す必要がありますSpringコールバックをトリガーするための_@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());
}
}
_
ポイントは、_@Bean
_アノテーション付きメソッドの呼び出しが、返されるBean(この場合はFactoryBean
)の初期化を実行するアスペクトによってインターセプトされるため、sqlSessionFactoryBean()
の呼び出しがsqlSessionFactory()
では、完全に初期化されたFactoryBean
を返します。
これは、自動配線に頼るときに最もよく解決されると思います。 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は、XML構成の場合と同様に、myFactory()。getObject()によって返されたMyBeanインスタンスを挿入します。
これは、@ Component/@ Serviceなどのクラスで@ Inject/@ Autowireを使用している場合にも機能します。
Spring JavaConfigには ConfigurationSupport クラスがあり、FactoryBeanで使用するgetObject()メソッドがありました。
あなたはそれを拡張して使うでしょう
@Configuration
public class MyConfig extends ConfigurationSupport {
@Bean
public MyBean getMyBean() {
MyFactoryBean factory = new MyFactoryBean();
return (MyBean) getObject(factory);
}
}
これにはいくつかの背景があります jira issue
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();
}
}
背景 ここ
これは私がやっていることであり、うまくいきます:
@Bean
@ConfigurationProperties("dataSource")
public DataSource dataSource() { // Automatically configured from a properties file
return new BasicDataSource();
}
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource); // Invoking dataSource() would get a new instance which won't be initialized
factory.setAnotherProperty(anotherProperty());
return factory;
}
@Bean
public AnotherBean anotherBean(SqlSessionFactory sqlSessionFactory) { // This method receives the SqlSessionFactory created by the factory above
return new AnotherBean(sqlSessionFactory);
}
宣言したBeanは、引数として他の@Beanメソッドに渡すことができます(同じメソッドを再度呼び出すと、Springによって処理されない新しいインスタンスが作成されます)。 FactoryBeanを宣言すると、作成したBeanタイプを別の@Beanメソッドの引数として使用でき、正しいインスタンスを受け取ります。あなたも使うことができます
@Autowired
private SqlSessionFactory sqlSessionFactory;
どこでも、それはうまくいきます。
ここに私がそれをやっている方法があります:
@Bean
def sessionFactoryBean: AnnotationSessionFactoryBean = {
val sfb = new AnnotationSessionFactoryBean
sfb.setDataSource(dataSource)
sfb.setPackagesToScan(Array("com.foo.domain"))
// Other configuration of session factory bean
// ...
return sfb
}
@Bean
def sessionFactory: SessionFactory = {
return sessionFactoryBean.getObject
}
SessionFactoryBeanが作成され、適切な作成後のライフサイクルが発生します(afterPropertiesSetなど)。
SessionFactoryBeanを直接Beanとして参照しないことに注意してください。 sessionFactoryを他のBeanに自動配線します。
AppConfigurationにファクトリを注入しないのはなぜですか?
@Configuration
public class AppConfig {
@Resource
private SqlSessionFactoryBean factory;
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
return factory.getObjectfactory();
}
}
しかし、あなたの質問が正しく理解できなかった可能性があります。何か奇妙なことをしようとしているように見えるので、少し戻って、本当に必要なものを再考してください。