How to use spring @Lookup annotation?

后端 未结 3 539
無奈伤痛
無奈伤痛 2020-12-05 05:55

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.

I\'m new

相关标签:
3条回答
  • 2020-12-05 06:25

    Before applying @Lookup annotation to your public MyClass2 myClass2() method, read this in @Lookup's 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 methods where we can't dynamically provide a subclass for them).

    So remove the following factory method style bean declaration from 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
    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.


    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):

    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.

    0 讨论(0)
  • 2020-12-05 06:25

    If you are not on Spring 4.1 you can use the provider injection instead:

    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.

    0 讨论(0)
  • 2020-12-05 06:27

    Also, you can declare myClass2 bean with TARGET_CLASS proxyMode.

      @Bean
      @Scope("prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
      public MyClass2 myClass2() {
        return new SidebarQuickMenuController();
      }
    
    0 讨论(0)
提交回复
热议问题