シングルトンからプロトタイプクラスを取得する必要があります。メソッドインジェクションが適切な方法であることがわかりましたが、Spring @Lookupアノテーションの使用方法がわかりません。
依存性注入は初めてなので、アノテーション構成を選択したので、その方向に進みたいと思います。
@Lookupアノテーションが最近追加されたことがわかりました( https://spring.io/blog/2014/09/04/spring-framework-4-1-ga-is-here )、しかし、それを使用する方法はどこにも見つかりません。
だから、これは簡単な例です
構成クラス:
@Configuration
@Lazy
public class ApplicationConfiguration implements ApplicationConfigurationInterface {
@Bean
public MyClass1 myClass1() {
return new ContentHolderTabPaneController();
}
@Bean
@Scope("prototype")
public MyClass2 myClass2() {
return new SidebarQuickMenuController();
}
}
そしてここにクラスの例があります:
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
public MyClass2 myClass2(){
}
}
@Lookupアノテーションを使用するにはどうすればよいですか?
_@Lookup
_アノテーションをpublic MyClass2 myClass2()
メソッドに適用する前に、これを @ LookupのJavadoc で読んでください。
コンテナは、CGLIBを介してメソッドを含むクラスのランタイムサブクラスを生成します。そのため、そのようなルックアップメソッドは、コンテナが通常のコンストラクタを通じてインスタンス化するBeanでのみ機能します(つまり、ルックアップメソッドはBeanで置き換えられません)ファクトリメソッドから返されます。これらのサブクラスを動的に提供することはできません)。
したがって、次のファクトリメソッドスタイルBean宣言をApplicationConfiguration
から削除します。
_ @Bean
public MyClass1 myClass1() {
return new ContentHolderTabPaneController();
}
_
そして_@Component
_アノテーションを追加して、SpringがBeanをインスタンス化できるようにします(メソッドに_@Lookup
_アノテーションも追加します):
_@Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
@Lookup
public MyClass2 myClass2(){
return null; // This implementation will be overridden by dynamically generated subclass
}
}
_
ここで、_myClass1
_ Beanをコンテキスト外で取得し、その_myClass2
_メソッドを置き換えるかオーバーライドして、毎回新しいプロトタイプBeanを取得する必要があります。
更新:
_@Lookup
_アノテーション付きメソッド(「ルックアップメソッド」)を実装することは難しくありません。 _@Lookup
_がなく、構成クラスを変更しない場合、_MyClass1
_は次のようになります(実際、_@Lookup
_が使用された場合、Springはサブクラスで同様の実装を生成します)。
_public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
@Autowired
private ApplicationContext applicationContext;
public MyClass2 myClass2() {
return applicationContext.getBean(MyClass2.class);
}
}
_
SpringがApplicationContext
を注入します。
Spring 4.1を使用していない場合は、代わりにプロバイダーインジェクションを使用できます。
public class MyClass1 {
@Autowired
private Provider<MyClass2> myClass2Provider;
doSomething() {
MyClass2 myClass2 = myClass2();
myClass2.fooBar()
}
public MyClass2 myClass2(){
return myClass2Provider.get();
}
}
これはDI、IoCであり、ルックアップメソッドの抽象クラスとxml定義を回避します。
また、TARGET_CLASS proxyModeを使用してmyClass2 Beanを宣言することもできます。
@Bean
@Scope("prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public MyClass2 myClass2() {
return new SidebarQuickMenuController();
}