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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 01:44:29  来源:igfitidea点击:

How to use spring @Lookup annotation?

javaspringdependency-injection

提问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 @Lookupannotation 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 @Componentannotation to let Spring instantiate the bean (also add the @Lookupannotation 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 myClass1bean out of context, and its myClass2method 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 @Lookupannotated method (the "lookup method"). Without @Lookupand keeping your configuration class unchanged, now MyClass1looks like (in fact Spring generates a similar implementation in a subclass if @Lookupwere 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 ApplicationContextfor 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();
  }