简介
说明
本文用示例介绍@Order(顺序)注解的用法。
@Order的作用:
- 多个 Bean 注入到集合时在集合中的顺序
- 指定AOP的优先级
- 控制ApplicationListener实现类的加载顺序
- 控制ApplicationRunner、CommandLineRunner实现类的加载顺序
@Order的使用
- Integer.MIN_VALUE <= Order <= Integer.MAX_VALUE。
- 最大最小优先级:@Order(Ordered.LOWEST_PRECEDENCE) / @Order(Ordered.HIGHEST_PRECEDENCE )
Spring已有的顺序值:org/springframework/core/Ordered:
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
int LOWEST_PRECEDENCE = Integer.MAX_VALUE; - Order值越小,优先级越高!
- @Order的使用位置: ElementType.TYPE, ElementType.METHOD, ElementType.FIELD
@Order不支持的操作:
- 不能指定 bean 的加载顺序
- 它对于实例的 bean 之间的加载顺序,没有任何影响。
- 无论使用@Order还是实现Ordered接口,都不行
- 不能指定@AutoConfigureOrder外部依赖的 AutoConfig 的加载顺序(即定义在/META-INF/spring.factories文件中的配置 bean 优先级)
- 在当前工程中使用这个注解并没有什么鸟用。
- 同样的 @AutoConfigureBefore和 @AutoConfigureAfter这两个注解的适用范围和@AutoConfigureOrder一样。
官方注释
{@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 用于切面的优先级指定;Spring4.0 之后它的功能进行了增强,支持集合的注入时,指定集合中 bean 的顺序。它对于实例的 bean 之间的顺序,没有任何影响。
用法1:控制集合顺序
接口
package com.example.test; public interface IBean { }
实现类1
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration public class DemoConfig1 { @Bean @Order(2) public DemoBean1 demo1Service(){ System.out.println("config-1 加载了"); return new DemoBean1(); } @Data private class DemoBean1 implements IBean{ private String name; private Integer age; } }
实现类2
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration public class DemoConfig2 { @Bean @Order(1) public DemoBean2 demo2Service(){ System.out.println("config-2 加载了"); return new DemoBean2(); } @Data private class DemoBean2 implements IBean{ private String name; private String phone; } }
测试类
package com.example.test; import org.springframework.stereotype.Component; import java.util.List; @Component public class CollectionIOC { public CollectionIOC(List<IBean> iBeans) { for (IBean iBean : iBeans) { System.out.println(iBean.getClass().getName()); } } }
执行结果
config-1 加载了 config-2 加载了 com.example.test.DemoConfig2$DemoBean2 com.example.test.DemoConfig1$DemoBean1
颠倒顺序
config-1 加载了 config-2 加载了 com.example.test.DemoConfig1$DemoBean1 com.example.test.DemoConfig2$DemoBean2
@Order放到这三个位置有相同的效果:@Bean、Bean类、@Component
例如:
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration public class DemoConfig2 { @Bean public DemoBean2 demo2Service(){ System.out.println("config-2 加载了"); return new DemoBean2(); } @Data @Order(1) private class DemoBean2 implements IBean{ private String name; private String phone; } }
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration public class DemoConfig2 { @Bean @Order(1) public DemoBean2 demo2Service(){ System.out.println("config-2 加载了"); return new DemoBean2(); } @Data private class DemoBean2 implements IBean{ private String name; private String phone; } }
用法2:AOP顺序
见:Spring之AOP-控制AOP的执行顺序 – 自学精灵
用法3:ApplicationListener顺序
见:SpringBoot-自定义事件-同步与异步 – 自学精灵
用法4:ApplicationRunner等顺序
无效的场景
@Bean + @Order,@Configuration+@Order都是无法确定顺序的。
@Bean + @Order(无效)
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration public class DemoConfig1 { @Bean @Order(1) public DemoBean1 demo1Service(){ System.out.println("config-1 加载了"); return new DemoBean1(); } @Data private class DemoBean1 { private String name; private Integer age; } }
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration public class DemoConfig2 { @Bean @Order(2) public DemoBean2 demo2Service(){ System.out.println("config-2 加载了"); return new DemoBean2(); } @Data private class DemoBean2 { private String name; private String phone; } }
执行结果
config-1 加载了 config-2 加载了
执行结果(颠倒Order)
config-1 加载了 config-2 加载了
@Configuration+@Order(无效)
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration @Order(1) public class DemoConfig1 { @Bean public DemoBean1 demo1Service(){ System.out.println("config-1 加载了"); return new DemoBean1(); } @Data private class DemoBean1 { private String name; private Integer age; } }
package com.example.test; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @Configuration @Order(2) public class DemoConfig2 { @Bean public DemoBean2 demo2Service(){ System.out.println("config-2 加载了"); return new DemoBean2(); } @Data private class DemoBean2 { private String name; private String phone; } }
执行结果
config-1 加载了 config-2 加载了
执行结果(颠倒@Order)
config-1 加载了 config-2 加载了
请先
!