Spring Boot Bean的创建顺序
Spring Boot是一个基于Spring框架的开源项目,它可以快速地创建和运行独立的、生产级的Spring应用程序。Spring Boot提供了很多特性,如自动配置、嵌入式服务器、外部化配置等,让开发者可以更专注于业务逻辑,而不是配置和依赖管理。
在Spring Boot中,Bean是一个由Spring容器管理的对象,它可以被注入到其他Bean中,实现依赖注入(DI)的功能。Bean的创建和初始化是由Spring容器负责的,但是有时候我们需要控制Bean的创建顺序,比如当一个Bean依赖于另一个Bean时,我们需要保证被依赖的Bean先被创建和初始化。
那么,如何控制Spring Boot Bean的创建顺序呢?本文将介绍四种常用的方法:SmartLifeCycle接口、@DependsOn注解、@Primary注解和@Order注解。
SmartLifeCycle接口
SmartLifeCycle接口是一个扩展了LifeCycle接口的接口,它定义了两个方法:getPhase()和isAutoStartup()。通过实现这个接口,我们可以控制Bean在容器启动时的执行顺序。
getPhase()方法返回一个整数值,表示Bean所处的阶段。阶段值越小,越早被执行;阶段值越大,越晚被执行。默认情况下,所有Bean都处于0阶段。
isAutoStartup()方法返回一个布尔值,表示Bean是否在容器启动时自动执行。如果返回true,则Bean会在容器启动时执行;如果返回false,则Bean需要手动调用start()方法才会执行。
例如,我们有两个Bean:A和B,A依赖于B,我们希望B先于A被执行。我们可以让B实现SmartLifeCycle接口,并返回-1作为阶段值,表示B是最先被执行的Bean。同时,我们也可以让A实现SmartLifeCycle接口,并返回1作为阶段值,表示A是稍后被执行的Bean。代码如下:
@Component
public class A implements SmartLifeCycle {
@Autowired
private B b;
@Override
public void start() {
System.out.println("A start");
}
@Override
public void stop() {
System.out.println("A stop");
}
@Override
public boolean isRunning() {
return false;
}
@Override
public int getPhase() {
return 1;
}
@Override
public boolean isAutoStartup() {
return true;
}
}
@Component
public class B implements SmartLifeCycle {
@Override
public void start() {
System.out.println("B start");
}
@Override
public void stop() {
System.out.println("B stop");
}
@Override
public boolean isRunning() {
return false;
}
@Override
public int getPhase() {
return -1;
}
@Override
public boolean isAutoStartup() {
return true;
}
}
运行结果如下:
B start
A start
可以看到,B先于A被执行。
@DependsOn注解
@DependsOn注解是一个用于指定Bean之间依赖关系的注解,它可以放在类或者方法上。通过使用这个注解,我们可以保证被依赖的Bean先于依赖它的Bean被创建和初始化。
例如,我们有两个Bean:C和D,C依赖于D,我们希望D先于C被创建和初始化。我们可以在C上使用@DependsOn注解,并指定D的名称。代码如下:
@Component
@DependsOn("d")
public class C {
@Autowired
private D d;
public C() {
System.out.println("C constructor");
}
@PostConstruct
public void init() {
System.out.println("C init");
}
}
@Component
public class D {
public D() {
System.out.println("D constructor");
}
@PostConstruct
public void init() {
System.out.println("D init");
}
}
运行结果如下:
D constructor
D init
C constructor
C init
可以看到,D先于C被创建和初始化。
@Primary注解
@Primary注解是一个用于指定Bean的优先级的注解,它可以放在类或者方法上。通过使用这个注解,我们可以在有多个同类型的Bean时,让Spring容器优先选择被标记为@Primary的Bean。
例如,我们有两个Bean:E和F,它们都实现了一个接口G。我们有另一个Bean:H,它需要注入一个G类型的Bean。我们希望Spring容器优先选择E作为H的依赖。我们可以在E上使用@Primary注解。代码如下:
@Component
@Primary
public class E implements G {
@Override
public void sayHello() {
System.out.println("Hello from E");
}
}
@Component
public class F implements G {
@Override
public void sayHello() {
System.out.println("Hello from F");
}
}
@Component
public class H {
@Autowired
private G g;
public void greet() {
g.sayHello();
}
}
运行结果如下:
Hello from E
可以看到,Spring容器选择了E作为H的依赖。
@Order注解
@Order注解是一个用于指定Bean的顺序值的注解,它可以放在类或者方法上。通过使用这个注解,我们可以在有多个同类型的Bean时,让Spring容器按照顺序值从小到大排序这些Bean,并将它们作为一个列表或者数组注入到其他Bean中。
例如,我们有三个Bean:I、J和K,它们都实现了一个接口L。我们有另一个Bean:M,它需要注入一个L类型的列表。我们希望Spring容器按照I、J、K的顺序将它们注入到M中。我们可以在I、J、K上使用@Order注解,并分别指定1、2、3作为顺序值。代码如下:
@Component
@Order(1)
public class I implements L {
@Override
public void sayHi() {
System.out.println("Hi from I");
}
}
@Component
@Order(2)
public class J implements L {
@Override
public void sayHi() {
System.out.println("Hi from J");
}
}
@Component
@Order(3)
public class K implements L {
@Override
public void sayHi() {
System.out.println("Hi from K");
}
}
@Component
public class M {
@Autowired
private List<L> list;
public void greetAll() {
for (L l : list) {
l.sayHi();
}
}
}
运行结果如下:
Hi from I
Hi from J
Hi from K
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名,转载请标明出处
最后编辑时间为:
2023/06/23 15:47