我需要从singleton获得原型类。我发现方法注入是可行的方法,但我真的不知道如何使用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注释执行此操作?
答案 0 :(得分:31)
在将@Lookup
注释应用于public MyClass2 myClass2()
方法之前,请先阅读@Lookup's Javadoc中的内容:
容器将通过CGLIB生成包含类的方法的运行时子类,这就是为什么这样的查找方法只能在容器通过常规构造函数实例化的bean上工作(即查找方法无法替换从工厂方法返回的bean ,我们无法为它们动态提供子类。)
因此从ApplicationConfiguration
中删除以下工厂方法样式bean声明:
@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
。
答案 1 :(得分:6)
如果您不在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定义。
答案 2 :(得分:0)
此外,您可以使用TARGET_CLASS proxyMode声明myClass2 bean。
@Bean
@Scope("prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public MyClass2 myClass2() {
return new SidebarQuickMenuController();
}