Springboot中的@Order如何使用

网友投稿 289 2022-08-30


Springboot中的@Order如何使用

在spring-boot 2.6.2下测试,@Order并不会影响bean的装载顺序,声明了@Component的类,无论是构造方法、@PostConstruct注解声明的方法,还是实现的InitializingBean接口中的afterPropertiesSet()方法,如果beanClass位于同样的目录层级,这些方法的调用只会受到className的顺序影响:

@Component

@Slf4j

@Order(2)

public class Bean1 implements InitializingBean {

public Bean1() {

log.info("construct bean1");

}

@Override

public void afterPropertiesSet() throws Exception {

log.info("initialled bean1");

}

@PostConstruct

public void post() {

log.info("post bean1");

}

}

@Component

@Slf4j

@Order(1)

public class Bean2 implements InitializingBean {

public Bean2() {

log.info("construct bean2");

}

@Override

public void afterPropertiesSet() throws Exception {

log.info("initialled bean2");

}

@PostConstruct

public void post() {

log.info("post bean2");

}

}

/* 结果打印顺序:

construct bean1

post bean1

initialled bean1

construct bean2

post bean2

initialled bean2

*/

观察@Order的注解说明,第一句写着: @Order defines the sort order for an annotated component. 提到这个注解只是对component排序,那么哪里会收到这个排序数值的影响呢?

这里先改造一下代码:

public interface IBean {

void work();

}

@Component

@Slf4j

@Order(2)

public class Bean1 implements InitializingBean,CommandLineRunner,IBean {

publihttp://c Bean1() {

log.info("construct bean1");

}

@Override

public void afterPropertiesSet() throws Exception {

log.info("initialled bean1");

}

@PostConstruct

public void post() {

log.info("post bean1");

}

@Override

public void run(String... args) throws Exception {

log.info("running bean1");

}

@Override

public void work() {

log.info("bean1 is working");

}

}

@Component

@Slf4j

@Order(1)

public class Bean2 implements InitializingBean, CommandLineRunner, IBean {

public Bean2() {

log.info("construct bean2");

}

@Override

public void afterPropertiesSet() throws Exception {

log.info("initialled bean2");

}

@PostConstruct

public void post() {

log.info("post bean2");

}

@Override

public void run(String... args) throws Exception {

log.info("running bean2");

}

@Override

public void work() {

log.info("bean2 is working");

}

}

@Service

@RequiredArgsConstructor

public class TestService {

private final List beans;

public void test(){

beans.forEach(IBean::work);

}

}

启动之后执行TestService的test方法,得到如下顺序的日志:

construct bean1post bean1initialled bean1construct bean2post bean2initialled bean2running bean2running bean1bean2 is workingbean1 is working

作一下说明,@Order会影响依赖注入的顺序,如果存在同样类型的多个bean,且依赖声明使用了List,会将所有bean实例按照Order声明的顺序放入一个ArrayList中注入,如果用的是Collection或者Set则无效,因为类型本身无序。

而CommandLineRunner声明的run方法,会在bean被IOC容器装配完成之后被调用,方法注释简单明了的一句Callback used to run the bean可以理解为bean实例真正构建完成之后的回调方法,而这个方法会受到@Order的顺序影响,效果前面日志中已经体现,这里贴一下类注释:

Interface used to indicate that a bean should run when it is contained wiUqLWDOEFthin a SpringApplication. Multiple CommandLineRunner beans can be defined within the same application context and can be ordered using the Ordered interface or @Order annotation.

除了以上两种用法,@Aspect声明的切面类、继承了OncePerRequestFilter的过滤器等,它们的作用顺序也会受到Order的影响。

注意:如果@Order注解配置在了@Configuration修饰的配置类中的@Bean方法修饰的方法上时,指定顺序并不会生效

顺便提一下另外一个注解:@Priority,以上@Order能起作用的地方,换成@Priority一样会生效,但在一种情况下,它的作用和@Order大为不同:

同一个接口类型有多个不同的bean实现类时,注入依赖时使用集合声明不会报错,但声明为单体类型时,如果各个Bean类使用了@Order声明,就会报required a single bean, but x were found的错误,这时有两种方法可以解决问题,一是在其中一个Bean类加上@Primary的注解声明为首要类型,另外一个就是把Order改成Priority,优先级最高的那个bean会被当作primary来对待。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:python鸡兔同笼问题(Python鸡兔同笼问题若无解怎么编)
下一篇:python_排序函数_本文文件内容排序(python对文件排序)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~