使用 Spring @Lazy 和 @PostConstruct 注释
Using Spring @Lazy and @PostConstruct annotations
我关注类:
@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 按如下方式初始化 bean:
1. 创建第一个 bean B。当创建 bean B 时,由于 @Lazy
注释,字段 a
将不会被初始化。
2. 接下来创建bean D。然后 method3()
将被执行,因为它被标记为 @PostConstruct
,但 bean A 尚未被 Spring 触及。因此,当调用 a.method1() 时,Spring 会创建 bean A 并将其注入字段 a
还是会抛出 NullPointerException
?
您需要了解,当您将 @Lazy
指定为注入的一部分时发生了什么。根据 documentation:
In addition to its role for component initialization, the @Lazy
annotation may also be placed on injection points marked with
@Autowired
or @Inject
. In this context, it leads to the injection of a
lazy-resolution proxy.
这意味着在启动时 Spring 将注入代理实例 class 而不是 class A
实例。代理 class 自动生成 class,与 class A
具有相同的接口。在第一次调用任何方法时,代理将在自身内部创建 class A
的实例。之后,所有方法的调用都将被重定向到 proxy.
内部的 class A
实例。
所以没有理由害怕任何问题。
我关注类:
@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 按如下方式初始化 bean:
1. 创建第一个 bean B。当创建 bean B 时,由于 @Lazy
注释,字段 a
将不会被初始化。
2. 接下来创建bean D。然后 method3()
将被执行,因为它被标记为 @PostConstruct
,但 bean A 尚未被 Spring 触及。因此,当调用 a.method1() 时,Spring 会创建 bean A 并将其注入字段 a
还是会抛出 NullPointerException
?
您需要了解,当您将 @Lazy
指定为注入的一部分时发生了什么。根据 documentation:
In addition to its role for component initialization, the
@Lazy
annotation may also be placed on injection points marked with@Autowired
or@Inject
. In this context, it leads to the injection of a lazy-resolution proxy.
这意味着在启动时 Spring 将注入代理实例 class 而不是 class A
实例。代理 class 自动生成 class,与 class A
具有相同的接口。在第一次调用任何方法时,代理将在自身内部创建 class A
的实例。之后,所有方法的调用都将被重定向到 proxy.
A
实例。
所以没有理由害怕任何问题。