SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣 (2)

然后我们将 Demo1, Demo3 放在一个配置中,Demo2 放在另外一个配置中

@Order(2) @Configuration public class AConf1 { @Bean public Demo1 demo1() { return new Demo1(); } @Bean public Demo3 demo3() { return new Demo3(); } } @Order(1) @Configuration public class BConf1 { @Bean public Demo2 demo2() { return new Demo2(); } }

如果@Order 注解实际上控制的是配置类中 Bean 的加载顺序,那么 BConf1 中的 Bean 应该优先加载,也就是说 Demo2 会优先于 Demo1, Demo3,实际测试一下,输出如

SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣

上面的输出结果和我们预期的并不一样,所以@Order注解来决定配置类的顺序也是不对的

2. @AutoConfigureOrder

从命名来看,这个注解是用来指定配置类的顺序的,然而对于这个注解的错误使用也是非常多的,而大多的错误使用在于没有真正的了解到它的使用场景

接下来我们来演示一下错误的使用 case

在工程内新建两个配置类,直接使用注解

@Configuration @AutoConfigureOrder(1) public class AConf2 { public AConf2() { System.out.println("A Conf2 init!"); } } @Configuration @AutoConfigureOrder(-1) public class BConf2 { public BConf2() { System.out.println("B conf2 init!"); } }

当注解生效时,BConf 会优先级加载

SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣

从输出结果来看,和我们预期的不一样;那么这个注解是不是作用于配置类中的 Bean 的顺序,而不是配置类本身呢?

同样的我们设计一个 case 验证一下

public class DemoA { private String name = "conf demo bean A"; public DemoA() { System.out.println(name); } } public class DemoB { private String name = "conf demo bean B"; public DemoB() { System.out.println(name); } } public class DemoC { private String name = "conf demo bean C"; public DemoC() { System.out.println(name); } }

对应的配置类

@Configuration @AutoConfigureOrder(1) public class AConf3 { @Bean public DemoA demoA() { return new DemoA(); } @Bean public DemoC demoC() { return new DemoC(); } } @Configuration @AutoConfigureOrder(-1) public class BConf3 { @Bean public DemoB demoB() { return new DemoB(); } }

如果 DemoB 后被加载,则说明上面的观点是错误的,实测结果如下

SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣

所以问题来了,@AutoConfigureOrder这个注解并不能指定配置类的顺序,还叫这个名,干啥?存粹是误导人不是!!!

接下来我们看一下@Order和@AutoConfigureOrder的正确使用方式

III. 使用说明 1. @Order

先看一下这个注解的官方注释

{@code @Order} defines the sort order for an annotated component.
Since Spring 4.0, annotation-based ordering is supported for many
kinds of components in Spring, even for collection injection where the order values
of the target components are taken into account (either from their target class or
from their {@code @Bean} method). While such order values may influence priorities
at injection points, please be aware that they do not influence singleton startup
order which is an orthogonal concern determined by dependency relationships and
{@code @DependsOn} declarations (influencing a runtime-determined dependency graph).

最开始 Order 注解用于切面的优先级指定;在 4.0 之后对它的功能进行了增强,支持集合的注入时,指定集合中 bean 的顺序

并且特别指出了,它对于但实例的 bean 之间的顺序,没有任何影响;这句话根据我们上面的测试也可以验证

接下来我们需要看一下通过@Order 注解来注入集合时,指定顺序的场景

首先我们定义两个 Bean 实现同一个接口,并添加上@Order注解

public interface IBean { } @Order(2) @Component public class AnoBean1 implements IBean { private String name = "ano order bean 1"; public AnoBean1() { System.out.println(name); } } @Order(1) @Component public class AnoBean2 implements IBean { private String name = "ano order bean 2"; public AnoBean2() { System.out.println(name); } }

然后再一个测试 bean 中,注入IBean的列表,我们需要测试这个列表中的 Bean 的顺序是否和我们定义的@Order规则一致

@Component public class AnoTestBean { public AnoTestBean(List<IBean> anoBeanList) { for (IBean bean : anoBeanList) { System.out.println("in ano testBean: " + bean.getClass().getName()); } } }

根据我们的预期, anoBeanList 集合中,anoBean2 应该在前面

SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣

根据上面的输出,也可以看出列表中的顺序和我们预期的一致,并且 AnoOrderBean1与 AnoOrderBean2 的加载顺序和注解没有关系

2. @AutoConfigureOrder

这个注解用来指定配置文件的加载顺序,然而前面的测试中并没有生效,那么正确的使用姿势是怎样的呢?

@AutoConfigureOrder适用于外部依赖的包中 AutoConfig 的顺序,而不能用来指定本包内的顺序

为了验证上面的说法,我们再次新建两个工程,并指定自动配置类的顺序

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygxws.html