Spring Bean加载顺序问题

Spring Bean加载顺序问题

问题背景

在基于前同事的项目进行改造重构中 其中有将一些强耦合属性关系抽出做成配置时
使用了静态变量存储(从nacos中获取的对象再使用@PostConstruct进行赋值) 本地正常运行
linux也运行正常 突然今晚给我说启动报错
在这里插入图片描述

问题

炸一看 这就是bean没注入好 第一反应时缺少了配置 然后没有看到相关的属性缺失
再考虑到依赖出现问题
沟通后得知可能出现再我的静态变量上 服务器变好了 加载顺序没有按照之前的来了?

分析

这种由于再自己电脑和dev环境服务器没有出现 加载顺序大概率是不会变的 但是测试服务器却出现了这样的问题 由于我使用了静态变量那么就可能出现再这个静态变量上
但是我静态变量已经用@PostConstruct进行加载了先附上各个代码

ControlTbmuServiceImpl 注入失败

@Service
@Slf4j
public class ControlTbmuServiceImpl implements ControlTbmuService {

    @Autowired
    private Msg0x303Handler msg0x303Handler;

Msg0x303Handler 调用静态失败

//TcbmuBootstrapConfig是配置类 用于处理nacos配置中心的集合对象
super.write(TcbmuBootstrapConfig.getTbmu().getPort().toString(), MSG_ID, sendMsg);//null

NettyClient 使用了TcbmuBootstrapConfig

@Configuration
@Slf4j
@Order(1)
//@RefreshScope
public class NettyClient implements CommandLineRunner {

    @Value("${netty.host}")
    private String host;

    @Autowired
    private TcbmuBootstrapConfig tcbmuBootstrapConfig;

TcbmuBootstrapConfig 处理配置数据

@Configuration
public class TcbmuBootstrapConfig {

    @Autowired
    private CarMachineConfig carMachineConfig;


    private static TbmuInfo tbmu; //tbmu对象
    private static List<CbmuSbmuInfo> cbmus = new CopyOnWriteArrayList<>(); //所有cbmu对象
    private static Map<String, CbmuSbmuInfo> cbmuMap = new ConcurrentHashMap<>(); //所有cbmu对象 key为sbmuNumber 这个只作为对象查询
    private static List<Integer> allPorts = new CopyOnWriteArrayList<>();    //所有端口

    public TcbmuBootstrapConfig() {
        System.out.println("TcbmuBootstrapConfig+++++++++++++++++++++++++++");
    }

    /**
     * 初始化
     */
//    public void intData(){
        System.out.println(111);
//        init();
//    }

    @PostConstruct
    private void init(){
        System.out.println("TcbmuBootstrapConfigInit++++++++++++++=====");
        tbmu = carMachineConfig.getTbmuList().get(0);
        cbmus = carMachineConfig.getCbmuSbmuList();
//        String jsonString = LocalJsonFileUtil.getFileJsonString(jsonFilePath);
//        tbmu = new TbmuInfo(LocalJsonFileUtil.getTbmuConfigData(jsonString).get(0).getPort());//默认只有一个tbmu
//        cbmus = LocalJsonFileUtil.getCbmuConfigData(jsonString);
        allPorts.add(tbmu.getPort());
        allPorts.addAll(cbmus.stream().map(CbmuSbmuInfo::getPort).distinct().collect(Collectors.toList()));
        cbmuMap = cbmus.stream().collect(Collectors.toConcurrentMap(CbmuSbmuInfo::getSbmuNumber, a->a,(k1, k2)->k1));
    }

CarMachineConfig 注入配置数据

@ConfigurationProperties(prefix = "car-machine")
@Component
@Data
public class CarMachineConfig implements Serializable {
    private List<TbmuInfo> tbmuList = new ArrayList<>();
    private List<CbmuSbmuInfo> cbmuSbmuList = new ArrayList<>();

    public CarMachineConfig() {
        System.out.println("CarMachineConfig++++++++++=");
    }
}

再说下基础的加载顺序

(1)在springBoot中是实现CommandLineRunner接口类

@Component
@Order(1)
class Runner1 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("step 3: The Runner1 run...");
    }
}

@Component
@Order(2)
class Runner2 implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("step 4: The Runner1 run...");
    }
}

(2)@SpringBootApplication(也就是我改动后的使用方式)

@EnableScheduling
@ComponentScan(basePackages = "com.swap")
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class CarmachineApplication {

    public CarmachineApplication(TcbmuBootstrapConfig config) {
    }
    public static void main(String[] args) {
        SpringApplication.run(CarmachineApplication.class, args);
    }
}

(3)声明一个实现了CommandLineRunner接口的Bean

@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootWebApplication.class, args);
    }
 
    @Bean
    public ApplicationStartupRunner schedulerRunner() {
        return new ApplicationStartupRunner();
    }
}
public class ApplicationStartupRunner implements CommandLineRunner {
    protected final Log logger = LogFactory.getLog(getClass());
    @Override
    public void run(String... args) throws Exception {
        logger.info("Application Started !!");
    }
}

(4)通过@Configuration注解类中bean的定义顺序控制bean的加载顺序;

@Configuration
public class BeanConfig {

    @Bean
    public TestInterface uiTest() {
        return new UiTest();
    }

    @Bean
    public TestInterface interTest() {
        return new InterTest();
    }

    @Bean
    public TestInterface unitTest() {
        return new UnitTest();
    }
}

(5) 等等等等。。

进一步分析

bean加载顺序 构造->@Autowire->@PostConstruct
需要注意@Configuration @Comment等是不会受其他类@Order(1)去影响他们的加载顺序的

目前处理 将TcbmuBootstrapConfig 类到启动类中第一个加载

太困了 待更~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值