2017-01-03 7 views
1

Я следующие классы:Использование Spring @Lazy и @PostConstruct аннотаций

@Repository 
class A { 

    public void method1() { 
     ... 
    } 
} 

@Component 
class B implements C { 

    @Autowired 
    @Lazy 
    private A a; 

    public void method2() { 
     a.method1(); 
    } 
} 

@Component 
class D { 

    @Autowired 
    private List<C> c; 

    @PostConstruct 
    public void method3() { 
     // iterate on list c and call method2() 
    } 
} 

Давайте предположим Spring инициализирует бобы следующим образом:
1. Первый компонент Б создается. Когда bean B создается, поле a не будет инициализировано из-за аннотации @Lazy.
2. Создан следующий bean-элемент D. Затем method3() будет выполнен, так как он отмечен @PostConstruct, но фаза A еще не коснулась весны. Поэтому, когда будет вызван a.method1(), будет ли Spring создавать bean-компонент A и ввести его в поле a или он будет кидать NullPointerException?

+2

Вы пытались запустить ту же настройку? – Arpit

+0

@Arpit Да, я сделал, и он ввел А в. Но я не могу гарантировать, что Spring придет сначала к A или D. Если он сначала дойдет до A, он сможет ввести A в течение некоторого времени, выполняя метод3(). Если он сначала дойдет до D, тогда проблема может возникнуть. – rohanagarwal

ответ

4

Вам необходимо понять, что происходит, когда вы указываете @Lazy как часть инъекции. В соответствии с documentation:

В дополнение к своей роли для компонента инициализации @Lazy аннотации также могут быть размещены на точках инжекции, отмеченные @Autowired или @Inject. В этом контексте это приводит к вводу прокси-сервер ленивого разрешения.

Это означает, что на старте Spring будет вводить экземпляр класса прокси-сервера вместо экземпляра класса A. Класс Proxy автоматически генерируется классом, который имеет тот же интерфейс, что и класс A. При первом вызове любого метода прокси создаст экземпляр класса A внутри себя. После этого все вызовы методов будут перенаправлены на этот экземпляр класса A внутри прокси.

Так что нет причин бояться каких-либо проблем.

+1

Я проверил это и да, это работает. Я проверил, что NPE не будет выбрано, и при первом вызове создается (экземпляр A). Добавление немного разъяснения про прокси, чтобы сделать вещи более ясными: Прокси - суррогатный объект или местозаполнитель для другого объекта для контроля доступа к нему. Поскольку прокси-сервер находится между вызывающим объектом и самим реальным объектом, он может решить запретить вызов действительного (или целевого) объекта или сделать что-то до того, как будет запущен целевой объект. – rohanagarwal