如何正确控制springboot中bean的加载顺序总结

1.为什么需要控制加载顺序

springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题。在此基础上,又提供了spi机制,用spring.factories可以完成一个小组件的自动装配功能。

在一般业务场景,可能你不大关心一个bean是如何被注册进spring容器的。只需要把需要注册进容器的bean声明为@Component即可,spring会自动扫描到这个Bean完成初始化并加载到spring上下文容器。

而当你在项目启动时需要提前做一个业务的初始化工作时,或者你正在开发某个中间件需要完成自动装配时。你会声明自己的Configuration类,但是可能你面对的是好几个有互相依赖的Bean。如果不加以控制,这时候可能会报找不到依赖的错误。

但是你明明已经把相关的Bean都注册进spring上下文了呀。这时候你需要通过一些手段来控制springboot中的bean加载顺序。

2.几个误区

在正式说如何控制加载顺序之前,先说2个误区。

在标注了@Configuration的类中,写在前面的@Bean一定会被先注册

这个不存在的,spring在以前xml的时代,也不存在写在前面一定会被先加载的逻辑。因为xml不是渐进的加载,而是全部parse好,再进行依赖分析和注册。到了springboot中,只是省去了xml被parse成spring内部对象的这一过程,但是加载方式并没有大的改变。

利用@Order这个标注能进行加载顺序的控制

严格的说,不是所有的Bean都可以通过@Order这个标注进行顺序的控制。你把@Order这个标注加在普通的方法上或者类上一点鸟用都没有。

那@Order能控制哪些bean的加载顺序呢,我们先看看官方的解释:

最开始@Order注解用于切面的优先级指定;在 4.0 之后对它的功能进行了增强,支持集合的注入时,指定集合中 bean 的顺序,并且特别指出了,它对于当 实例的 bean 之间的顺序,没有任何影响。

目前用的比较多的有以下3点:

  • 控制AOP的类的加载顺序,也就是被@Aspect标注的类
  • 控制ApplicationListener实现类的加载顺序
  • 控制CommandLineRunner实现类的加载顺序

3.如何控制

3.1@DependsOn

@DependsOn注解可以用来控制bean的创建顺序,该注解用于声明当前bean依赖于另外一个bean。所依赖的bean会被容器确保在当前bean实例化之前被实例化。

示例:

以上代码bean的加载顺序为:

@DependsOn的使用:

直接或者间接标注在带有@Component注解的类上面;

直接或者间接标注在带有@Bean注解的方法上面;

使用@DependsOn注解到类层面仅仅在使用 component-scanning 方式时才有效,如果带有@DependsOn注解的类通过XML方式使用,该注解会被忽略,<bean depends-on="..."/>这种方式会生效。

3.2 参数注入

在@Bean标注的方法上,如果你传入了参数,springboot会自动会为这个参数在spring上下文里寻找这个类型的引用。并先初始化这个类的实例。

利用此特性,我们也可以控制bean的加载顺序。

示例:

以上结果,beanB先于beanA被初始化加载。

需要注意的是,springboot会按类型去寻找。如果这个类型有多个实例被注册到spring上下文,那你就需要加上@Qualifier("Bean的名称")来指定

3.3 利用bean的生命周期中的扩展点

在spring体系中,从容器到Bean实例化&初始化都是有生命周期的,并且提供了很多的扩展点,允许你在这些步骤时进行逻辑的扩展。

这些可扩展点的加载顺序由spring自己控制,大多数是无法进行干预的。我们可以利用这一点,扩展spring的扩展点。在相应的扩展点加入自己的业务初始化代码。从来达到顺序的控制。

3.4 @AutoConfigureOrder

这个注解用来指定配置文件的加载顺序。但是在实际测试中发现,以下这样使用是不生效的:

无论你2个数字填多少,都不会改变其加载顺序结果。

那这个@AutoConfigureOrder到底是如何使用的呢。

经过测试发现,@AutoConfigureOrder只能改变外部依赖的@Configuration的顺序。如何理解是外部依赖呢。

能被你工程内部scan到的包,都是内部的Configuration,而spring引入外部的Configuration,都是通过spring特有的spi文件:spring.factories

换句话说,@AutoConfigureOrder能改变spring.factories中的@Configuration的顺序。

具体使用方式:

spring.factories:

4.总结

其实在工作中,我相信很多人碰到过复杂的依赖关系的bean加载,把这种不确定性交给spring去做,还不如我们自己去控制,这样在阅读代码的时候 ,也能轻易看出bean之间的依赖先后顺序。

        资源获取:

大家点赞、收藏、关注、评论啦 、查看👇🏻👇🏻👇🏻微信公众号获取联系方式👇🏻👇🏻👇🏻

 精彩专栏推荐订阅:下方专栏👇🏻👇🏻👇🏻👇🏻

每天学四小时:Java+Spring+JVM+分布式高并发,架构师指日可待

<think>嗯,用户现在问的是Spring Boot如何控制类的加载顺序。之前他们问过数据库连接池的好处,可能现在转向了Spring Boot的具体使用问题。我需要先理解用户的需求,他们可能在开发过程中遇到了类加载顺序的问题,比如Bean之间的依赖问题,或者某些配置类没有按预期加载。 首先,用户可能对Spring Boot的自动配置机制不太熟悉,或者他们在自定义配置时遇到了顺序问题。比如,他们可能希望某个Bean在另一个Bean之前初始化,或者某些配置类需要在特定的时间点加载。这时候,控制类的加载顺序就显得很重要了。 接下来,我需要回忆Spring Boot中控制加载顺序的常用方法。常见的包括使用@DependsOn注解,@Order注解,@AutoConfigureOrder,以及通过配置文件的spring.autoconfigure.exclude属性。此外,Bean的初始化方法和@PostConstruct也可能影响顺序。另外,实现特定的接口如PriorityOrdered或Ordered也是方法之一。 需要注意的是,不同的注解适用于不同的场景。比如@DependsOn主要用于Bean之间的显式依赖,而@Order通常用于AOP或列表排序。可能用户需要的是在配置类或Bean定义时的顺序控制,因此需要明确每种方法的使用场景。 同时,用户可能对Spring Boot的自动配置原理不太清楚,比如自动配置类是如何按顺序加载的。这时候可能需要解释@AutoConfigureAfter和@AutoConfigureBefore,这些是Spring Boot内部用来控制自动配置类顺序的注解,用户也可以利用这些来调整自己的配置类顺序。 还要考虑用户可能的误区,比如认为@Order可以控制所有Bean加载顺序,但实际上@Order主要用于某些特定情况,如拦截器的顺序。这时候需要指出正确的使用方法,避免误导。 另外,用户可能需要具体的例子来理解如何应用这些注解,比如在配置类上使用@Order,或者在Bean定义时使用@DependsOn。提供示例代码会更有帮助,但用户的问题中没有要求代码,所以可能需要在解释时提到这些例子。 最后,总结各个方法的适用场景,帮助用户根据具体需求选择合适的方式。同时提醒他们Spring容器本身的Bean加载机制,比如默认按声明顺序加载,但受到依赖关系的影响,所以显式控制有时是必要的。</think>在 Spring Boot 中,类的加载顺序(尤其是 Bean 的创建和初始化顺序)主要依赖于 Spring 容器的管理机制,但开发者可以通过以下方式显式控制加载顺序: --- ### **1. 使用 `@DependsOn` 注解** - **作用**:声明某个 Bean 依赖其他 Bean,确保依赖的 Bean 优先初始化。 - **适用场景**:Bean A 必须在 Bean B 创建前完成初始化时。 - **示例**: ```java @Component @DependsOn("beanB") // 要求先初始化 beanB public class BeanA { // ... } @Component public class BeanB { // ... } ``` --- ### **2. 通过 `@Order` 注解或 `Ordered` 接口** - **作用**:控制 Bean加载顺序(数值越小优先级越高),**主要用于影响 Bean 的注入顺序**(如列表中的 Bean 排序)。 - **适用场景**:AOP 切面、事件监听器、过滤器等需要顺序控制的组件。 - **示例**: ```java @Component @Order(1) // 优先级最高 public class HighPriorityBean implements Ordered { @Override public int getOrder() { return 1; } } ``` --- ### **3. 使用 `@AutoConfigureOrder` 和 `@AutoConfigureBefore`/`@AutoConfigureAfter`** - **作用**:控制自动配置类(`@Configuration`)的加载顺序。 - **适用场景**:自定义配置类需要优先于或晚于 Spring Boot 内置的自动配置类加载。 - **示例**: ```java @Configuration @AutoConfigureOrder(10) // 数值越小越优先(默认自动配置类的 Order=0) @AutoConfigureBefore(DataSourceAutoConfiguration.class) // 在数据源自动配置前加载 public class MyCustomConfig { // ... } ``` --- ### **4. 通过 `BeanFactoryPostProcessor` 干预** - **作用**:在 Bean 定义加载后、实例化前,动态修改 Bean 的定义(如依赖关系)。 - **适用场景**:需要编程式调整 Bean 的初始化顺序。 - **示例**: ```java @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { BeanDefinition beanA = beanFactory.getBeanDefinition("beanA"); beanA.setDependsOn("beanB"); // 强制 beanA 依赖 beanB } } ``` --- ### **5. 利用 `@PostConstruct` 和初始化方法** - **作用**:控制 Bean 初始化方法的执行顺序(但不影响 Bean 的创建顺序)。 - **示例**: ```java @Component public class BeanA { @PostConstruct public void init() { // 在 Bean 创建后执行,但无法保证与其他 Bean 的 init 方法顺序 } } ``` --- ### **6. 配置 `spring.autoconfigure.exclude`** - **作用**:排除特定的自动配置类,间接控制加载顺序。 - **示例**(`application.properties`): ```properties spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration ``` --- ### **总结:核心原则** 1. **隐式依赖优先**:Spring 默认按 Bean 的依赖关系自动管理加载顺序。 2. **显式控制补充**:当隐式依赖无法满足需求时,再通过注解或接口显式控制。 3. **避免过度干预**:过度控制加载顺序可能导致代码耦合,优先依赖 Spring 的自动管理机制。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值