В чем разница между аннотацией @Lazy и атрибутом lazy-initтег? - PullRequest
0 голосов
/ 25 декабря 2018

Насколько я понимаю, аннотация @Lazy и атрибут lazy-init тега должны иметь одинаковую функциональность.Но когда я разработал следующий код, он показывает различное поведение.В следующем коде я ожидал: - (Ошибка круговой зависимости)

org.springframework.beans.factory.BeanCurrentlyInCreationException

Я прикрепил код с помощью аннотации @Lazy, согласно моим ожиданиям, он не должен допускать циклическую зависимость.

@Component
public class A {
   private B b;
   @Autowired
   public A(@Lazy B b) {
         System.out.println("A.A() - 1-param Constructor");
         this.b = b;
   }    
}

@Component
public class B {
   private A a;
   @Autowired
   public B(A a) {
         System.out.println("B.B() - 1-param Constructor");
         this.a = a;
   }        
} 

Основной класс:

public class AnnotationApp{
    public static void main(String[] args){
         ApplicationContext ctx = new ClassPathXmlApplicationContext("com/ry/cfgs/annotationAppContext.xml"); 
         B objB = ctx.getBean("b", B.class); 
         A objA = ctx.getBean("a", A.class);
    }
}

Файл конфигурации пружины:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-4.3.xsd">

     <context:component-scan base-package="com.ry.beans.annotation"></context:component-scan>

</beans>

ВЫХОД: -

AA () - Конструктор с 1 параметром

BB () - Конструктор с 1 параметром

Требуется объяснение, почему он так себя ведет?

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

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

См. Эту ссылку , которая объясняет, что это такое.Процитируем это здесь:

Circular dependencies

If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.

For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.

One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.

Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken-and-egg scenario).

Когда вы добавили public A(@Lazy B b) { .. } с помощью @Lazy, Spring вставит экземпляр Proxy B (обычно CGLIB) вместо простого B.В результате ему НЕ нужно создавать экземпляр, и это сработало.Попробуйте удалить @Lazy, и вы столкнетесь с проблемой, о которой вы упомянули.

Способы избежания циклических зависимостей:

  1. Используйте @Lazy, как вы это сделали
  2. Используйте инъекцию сеттера вместо инженера-конструктора

В этой ссылке

приведены некоторые другие приемы
0 голосов
/ 25 декабря 2018

Из Spring Framework Documentation :

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

Таким образом, в следующем коде:

@Autowired
public A(@Lazy B b) {
    // ...
}

b будет введено (с автоматической проводкой) первый доступ вместо запуска.

Теперь, если вы измените свой код на следующее:

@Autowired
public A(@Lazy B b) {
    System.out.println("A.A() - 1-param Constructor");
    System.out.println(b.toString());
    this.b = b;
}

, вы увидите, чтоorg.springframework.beans.factory.BeanCurrentlyInCreationException брошен.

...