Подтвердить что ты не робот

Как использовать аннотацию spring @Lookup?

Мне нужно получить класс прототипов из 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?

4b9b3361

Ответ 1

Прежде чем применять аннотацию @Lookup к вашему методу public MyClass2 myClass2(), прочитайте это в @Lookup Javadoc:

контейнер будет генерировать подклассы времени выполнения метода, содержащего класс через CGLIB, поэтому методы поиска могут работать только на beans, которые контейнер создает через регулярные конструкторы (т.е. методы поиска не могут быть заменены на beans возвращается из factory методов, где мы не можем динамически предоставлять подкласс для них).

Итак, удалите следующий factory метод style 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 каждый раз.


Update:

Использование объявления метода factory

Не сложно реализовать аннотированный метод @Lookup ( "метод поиска" ). Без @Lookup и сохраняя ваш класс конфигурации без изменений, теперь выглядит myClass1 (фактически Spring создает аналогичную реализацию в подклассе, если @Lookup):

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 для вас.

Ответ 2

Если вы не на 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 для методов поиска.