springboot中bean的加载顺序问题
一、为什么要控制
当你在项目启动时需要提前做一个业务的初始化工作时,或者你正在开发某个中间件需要完成自动装配时。
你会声明自己的Configuration类,但是可能你面对的是好几个有互相依赖的Bean。
如果不加以控制,这时候可能会报找不到依赖的错误,这个时候需要通过一些手段来控制springboot中的bean加载顺序。
二、怎么控制
@DependsOn
@DependsOn注解可以用来控制bean的创建顺序,该注解用于声明当前bean依赖于另外一个bean。
所依赖的bean会被容器确保在当前bean实例化之前被实例化。
与@Component或@Bean配合使用
demo
@Slf4j @Configuration @ConfigurationProperties(prefix = "dict") public class SpringConfig { @Component(value = "EventSource") public class EventSource { public EventSource(){ System.out.println("事件源创建"); } } /** * 监听类 */ @Component @DependsOn(value = {"EventSource"}) public class EventTListener { public EventTListener(){ System.out.println("监听器创建"); } } }
参数注入
package com.sinosoft.springbootplus.test.config; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; /** * @author lsh * @date 2022/2/25 */ @Slf4j @Configuration @ConfigurationProperties(prefix = "dict") public class SpringConfig { @Component public class Event{ public Event(){ System.out.println("事件事件"); } } @Component public class EventSource{ public EventSource(Event e){ System.out.println("事件源创建"); } } @Component public class EventTListener { public EventTListener(){ System.out.println("监听器创建"); } } }
利用bean的生命周期中的扩展点
@AutoConfigureOrder
@AutoConfigureOrder只能改变外部依赖的@Configuration的顺序。
这是不对的用法
@Slf4j @Configuration @ConfigurationProperties(prefix = "dict") public class SpringConfig { @Component @AutoConfigureOrder(1) public class Event{ public Event(){ System.out.println("事件事件"); } } @Component @AutoConfigureOrder(2) public class EventSource{ public EventSource(Event e){ System.out.println("事件源创建"); } } @Component @AutoConfigureOrder(3) public class EventTListener { public EventTListener(){ System.out.println("监听器创建"); } } }
以上内容发现,在config里配置是不起作用的。
这是正确的用法
创建两个配置类
@Slf4j @Configuration @AutoConfigureOrder(1) public class SpringConfig { @Component public class Event{ public Event(){ System.out.println("首先在SpringConfig"); } } } @Slf4j @Configuration @AutoConfigureOrder(2) public class NewConfig { @Component public class Event{ public Event(){ System.out.println("然后在NewConfig"); } } }
测试
发现结果是不正确的,注解还是没有生效。
当前工程里增加配置 META-INF/spring.factories,内容为项目中的配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sinosoft.springbootplus.common.config.NewConfig,com.sinosoft.springbootplus.common.config.SpringConfig
测试结果如图(正确)
三、遇到的问题
需要根据配置决定生成哪个实现类
当在配置文件中配置的dict.cacheType的值是local时,初始化LocalISysDictRepository交给spring容器管理;
当项目依赖了redis并且配置文件中配置的dict.cacheType的值是redis时,初始化RedisISysDictRepository交给spring容器管理。
但是我又在这两个实现类上加了@Repository注解
也要交给Spring管理,这个时候项目启动就报错了。(通俗的来说一个类只能一次交给Spring管理)
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
浅谈java中replace()和replaceAll()的区别
这篇文章主要介绍了java中replace()和replaceAll()的区别,两者都是常用的替换字符的方法,感兴趣的小伙伴们可以参考一下2015-11-11Java Big Number操作BigInteger及BigDecimal类详解
这篇文章主要为大家介绍了Java Big Number操作BigInteger及BigDecimal类详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2022-07-07Java Stream比较两个List的差异并取出不同的对象四种方法
今天开发一个需求时要对A和B两个List集合遍历,并比较出集合A有,而集合B没有的值,下面这篇文章主要给大家介绍了关于Java Stream比较两个List的差异并取出不同对象的四种方法,需要的朋友可以参考下2024-01-01
最新评论