原创

浅析springboot bean加载顺序

1、问题

  • 非spring管理的class中使用SpringContextUtil获取springbean报空指针
  • order指定的bean的加载顺序无效

上述问题,你是否在开发中遇到过,有没有搞清楚其中的缘由。

2、问题分析

@Component
public class SpringContextUtil implements ApplicationContextAware {

  private static ApplicationContext applicationContext = null;

  public SpringTool() {}

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    if (Objects.isNull(SpringTool.applicationContext)) {
      SpringTool.applicationContext = applicationContext;
    }
  }

  public static final ApplicationContext getApplicationContext() {
    return applicationContext;
  }

  public static final <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    return applicationContext.getBean(name, requiredType);
  }

  public static final <T> T getBean(Class<T> requiredType) throws BeansException {
    return applicationContext.getBean(requiredType);
  }

  public static final <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
    return applicationContext.getBean(requiredType, args);
  }
}

上面是springcontextUtil的代码,空指针的问题,明显是SpringContextUtil这个类还没有被spring加载过。

那么为什么没有没加载?加载顺序是什么?

3、详细分析

3.1、加载的机制

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Application.class}) // “Application.class”要是启动类
  • RunWith 指定以spring容器的方式执行单测
  • SpringBootTest指定了启动类Application
  • Application上的注解@ComponentScan指定的扫描的package
  • bean的注入按照指定扫描的先后顺序,同级按照类型的排序进行注入

空指针的问题就是因为springcontextUtil加载晚于构造函数所在的bean.因为springcontextUtil也是一个普通的由spring管理的bean.解决空指针,其中一个办法是提高的加载的优先级。

spring bean的注入核心代码

3.2、@order不能控制bean的加载顺序

惯性思维想通过order来控制bean的加载顺序,实践证明,想法是不成立的。

spring order注解无法控制bean的加载顺序

注解@Order或者接口Ordered的作用是定义SprinIOC容器中Bean的执行顺序的优先级,

而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响

order的控制场景主要是 aop和filter的执行顺序,非spring bean的加载顺序。

3.3、@DependsOn间接控制bean的加载顺序

  @Bean
  @DependsOn({"drdsDataSource"})
  public Db db(@Qualifier("drdsDataSource") DataSource datasource) {
    return Db.use(datasource);
  }

@DependsOn指定bean的依赖顺序。被依赖的会优先于bean提前加载

4、问题拓展

Spring Boot下控制配置执行顺序的三大直接

  • @AutoConfigureBefore
  • @AutoConfigureAfter
  • @AutoConfigureOrder

使用注意事项

  • 挪动到Application扫描不到的包内,切记:一定且必须是扫描不到的包内

  • 开启org.springframework.boot.autoconfigure.EnableAutoConfiguration

  • 当前工程里增加配置META-INF/spring.factories

@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder`这三个注解只能作用于自动配置类,而不能是自定义的@Configuration配置类。

适合各种starter的自由装配,开箱即用

正文到此结束
本文目录