Spring控制bean加载顺序使用详解
1.误区
1.1 使用@Order注解去设置Ben的加载顺序(Order里面的数值越小优先级越高)
分别创建Config1,Config2
@Component
@Order(1)
public class Config1 {
public Config1(){
System.out.println("Config1构建了.........");
}
}
@Component
@Order(2)
public class Config2 {
public Config2(){
System.out.println("Config2构建了.........");
}
}
期间我还尝试着将@Component都改为使用@Configuration,结果仍然不变
总结:尝试过同包下,不同包下。最终测试结果为:一般情况下会按照SPring类的书写的顺序去创建,但是也不一定,最终其实得看你的编译出来的文件,的Class文件到底是什么样子的,包括操作系统文件的排序规则等一系列的因素。反正这个顺序是不确定的。如果包的顺序Config1在Config2的下面,就算Config1的@Order值小于Config2的值也没有用。
1.2使用@AutoConfigureAfter控制Ben的加载顺序(当前配置类在指定配置类之后执行)
@AutoConfigureBefore(当前配置类在指定配置类之前执行)
@AutoConfigureOrder(指定优先级,数值越小,优先级越高)
@Configuration
@AutoConfigureAfter(Config1.class)
public class Config2 {
public Config2(){
System.out.println("Config2构建了.........");
}
}
@Configuration
public class Config1 {
public Config1(){
System.out.println("Config1构建了.........");
}
}@Configuration
@AutoConfigureAfter(Config1.class)
public class Config2 {
public Config2(){
System.out.println("Config2构建了.........");
}
}
@Configuration
public class Config1 {
public Config1(){
System.out.println("Config1构建了.........");
}
}@Configuration
@AutoConfigureOrder(1)
public class Config2 {
public Config2(){
System.out.println("Config2构建了.........");
}
}
@Configuration
@AutoConfigureOrder(2)
public class Config1 {
public Config1(){
System.out.println("Config1构建了.........");
}
}以上三个注解在同包和不同包都是不起作用的,和@Order是一样的也是通过书写顺序去创建的。
此时这里使用@Component是不起作用的,但是上面的@Order注解就不会有影响,无聊是使用@Configurantion还是@Component都是一个效果。
解决:在resources下新建META-INF/spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.juzi.test.config.Config2,\ com.juzi.test.config.Config1
结果我就不粘出来了,感兴趣的小伙伴可以去尝试一下。
2.正确的控制方法
2.1使用@DependsOn("Bean B")注解控制(告诉Spring容器Bean B 应该被提前初始化)
创建AircraftTask、CarTask、TrainTask

目前创建的顺序是 Aircraft -> CarTask -> Train
理想的创建顺序 Train -> Aircraft -> TrainCar
@Configuration
@DependsOn("trainTask")
public class AircraftTask {
@PostConstruct
public void init(){
System.out.println("Aircraft获取Train存入redis的数据..........");
}
}
@Configuration
@DependsOn("aircraftTask")
public class CarTask {
@PostConstruct
public void init(){
System.out.println("CarTask获取到Aircraft的数据..........");
}
}
@Configuration
public class TrainTask {
@PostConstruct
public void init(){
System.out.println("Train初查询数据存入redis..........");
}
}结果:和理想的结果一致

但是如果像以上这种依赖的类数量过多的话这样写注解容易写错,我们可以使用以下方法 :
2.2使用BeanDefinitionRegistryPostProcessor和ApplicationContextInitializer去控制
对这两个类不是很熟悉的同学可以去下载Spring源码简单的阅读一下。
public class CarTask {
@PostConstruct
public void init(){
System.out.println("CarTask获取到Aircraft的数据..........");
}
}
public class AircraftTask {
@PostConstruct
public void init(){
System.out.println("Aircraft获取Train存入redis的数据..........");
}
}
public class TrainTask {
@PostConstruct
public void init(){
System.out.println("Train初查询数据存入redis..........");
}
}这里不需要使用@Configuration或@Component注解,下面会对它们进行手动的添加到容器中。
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
AbstractBeanDefinition beanDefinition2 = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition2.setBeanClass(TrainTask.class);
registry.registerBeanDefinition("trainTask",beanDefinition2);
AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition1.setBeanClass(AircraftTask.class);
registry.registerBeanDefinition("aircraftTask",beanDefinition1);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(CarTask.class);
registry.registerBeanDefinition("carTaskTask",beanDefinition);
//相当于往Spring容器初始化的时的那个List里面添加了一个Bean 只要在扫描之前执行了postProcessBeanDefinitionRegistry 方法 那么就会安装List里面存放的顺序
//生成Bean
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}public class MyApplicationContextInitiaLizer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
configurableApplicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
}
}resources下新建META-INF/spring.factories文件 配置MyApplicationContextInitiaLizer的全限定类名即可。
#org.springframework.context.ApplicationContextInitializer=com.example.demo11.config.MyApplicationContextInitiaLizer
结果:也和预期的一致

以上就是Spring控制bean加载顺序使用详解的详细内容,更多关于Spring控制bean加载顺序的资料请关注脚本之家其它相关文章!
相关文章
springcloud gateway实现简易版灰度路由步骤详解
这篇文章主要为大家介绍了springcloud gateway实现简易版灰度路由步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-11-11
Springboot中Aspect切面的实现方式(以记录日志为例)
这篇文章主要介绍了Springboot中Aspect切面的实现方式(以记录日志为例),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-06-06
Mybatis-plus的selectPage()分页查询不生效问题解决
本文主要介绍了Mybatis-plus的selectPage()分页查询不生效问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2023-01-01
实现一个基于Servlet的hello world程序详解步骤
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层2022-02-02
SpringBoot 使用 Ehcache 作为缓存的操作方法
这篇文章主要介绍了SpringBoot 如何使用 Ehcache 作为缓存,我们通过添加 Ehcache 依赖、创建 Ehcache 配置文件并在 Spring Boot 应用程序的配置文件中启用 Ehcache 缓存,来配置 Ehcache 缓存,需要的朋友可以参考下2023-06-06


最新评论