浅析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.解决空指针,其中一个办法是提高的加载的优先级。
3.2、@order不能控制bean的加载顺序
惯性思维想通过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的自由装配,开箱即用
正文到此结束
- 本文标签: Spring Spring Boot
- 版权声明: 本站原创文章,于2021年08月31日由Mars发布,转载请注明出处