Java 如何使用 spring @Lookup 注释?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26028341/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use spring @Lookup annotation?
提问by Miljac
I need to get prototype class from singleton. I found that method injection is the way to go, but I don't really know how to use spring @Lookup annotation.
我需要从单例中获取原型类。我发现方法注入是要走的路,但我真的不知道如何使用 spring @Lookup 注释。
I'm new to dependency-injection, and I chose to go with annotation configuration, so I would like to continue in that direction.
我是依赖注入的新手,我选择使用注释配置,所以我想继续朝这个方向发展。
I found out that @Lookup annotation was added only recently (https://spring.io/blog/2014/09/04/spring-framework-4-1-ga-is-here), but I cannot find anywhere how to use it.
我发现 @Lookup 注释是最近才添加的(https://spring.io/blog/2014/09/04/spring-framework-4-1-ga-is-here),但我找不到任何方法用它。
So, here is simplified example
所以,这里是简化的例子
Configuration class:
配置类:
@Configuration
@Lazy
public class ApplicationConfiguration implements ApplicationConfigurationInterface {
@Bean
public MyClass1 myClass1() {
return new ContentHolderTabPaneController();
}
@Bean
@Scope("prototype")
public MyClass2 myClass2() {
return new SidebarQuickMenuController();
}
}
And here is class example:
这是类示例:
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
public MyClass2 myClass2(){
}
}
How do I do that with @Lookup annotation?
我如何使用 @Lookup 注释来做到这一点?
采纳答案by qingbo
Before applying @Lookup
annotation to your public MyClass2 myClass2()
method, read this in @Lookup's Javadoc:
在将@Lookup
注释应用于您的public MyClass2 myClass2()
方法之前,请阅读@Lookup 的 Javadoc 中的内容:
the container will generate runtime subclasses of the method's containing class via CGLIB, which is why such lookup methods can only work on beans that the container instantiates through regular constructors (i.e. lookup methods cannot get replaced on beans returned from factory methodswhere we can't dynamically provide a subclass for them).
容器将通过 CGLIB 生成方法包含类的运行时子类,这就是为什么这样的查找方法只能在容器通过常规构造函数实例化的 bean 上工作(即查找方法不能在从工厂方法返回的 bean 上被替换,而我们不能动态地为它们提供一个子类)。
So remove the following factory method style bean declaration from ApplicationConfiguration
:
因此,从以下工厂方法样式 bean 声明中删除ApplicationConfiguration
:
@Bean
public MyClass1 myClass1() {
return new ContentHolderTabPaneController();
}
and add @Component
annotation to let Spring instantiate the bean (also add the @Lookup
annotation to the method):
并添加@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
}
}
Now get myClass1
bean out of context, and its myClass2
method should have been replaced/overridden to get a new prototype bean each time.
现在myClass1
从上下文中获取bean,并且myClass2
每次都应该替换/覆盖它的方法以获取新的原型 bean。
Update:
更新:
Using factory method declaration
使用工厂方法声明
It's not hard to implement the @Lookup
annotated method (the "lookup method"). Without @Lookup
and keeping your configuration class unchanged, now MyClass1
looks like (in fact Spring generates a similar implementation in a subclass if @Lookup
were used):
实现带@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 injects the ApplicationContext
for you.
SpringApplicationContext
为你注入了。
回答by Josh
If you are not on Spring 4.1 you can use the provider injection instead:
如果您不在 Spring 4.1 上,则可以改用提供程序注入:
public class MyClass1 {
@Autowired
private Provider<MyClass2> myClass2Provider;
doSomething() {
MyClass2 myClass2 = myClass2();
myClass2.fooBar()
}
public MyClass2 myClass2(){
return myClass2Provider.get();
}
}
This is DI, IoC, avoids abstract classes and xml definitions for lookup methods.
这就是 DI,IoC,避免了查找方法的抽象类和 xml 定义。
回答by Michael Starodynov
Also, you can declare myClass2 bean with TARGET_CLASS proxyMode.
此外,您可以使用 TARGET_CLASS proxyMode 声明 myClass2 bean。
@Bean
@Scope("prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public MyClass2 myClass2() {
return new SidebarQuickMenuController();
}