当前位置: 代码网 > it编程>编程语言>Java > Spring控制Bean加载顺序的操作方法

Spring控制Bean加载顺序的操作方法

2024年05月28日 Java 我要评论
前言正常情况下,spring 容器加载 bean 的顺序是不确定的,那么我们如果需要按顺序加载 bean 时应如何操作?本文将详细讲述我们如何才能控制 bean 的加载顺序。场景我创建了 4 个 cl

前言

正常情况下,spring 容器加载 bean 的顺序是不确定的,那么我们如果需要按顺序加载 bean 时应如何操作?本文将详细讲述我们如何才能控制 bean 的加载顺序。

场景

我创建了 4 个 class 文件,分别命名为

  • firstinitialization
  • secondinitialization
  • thirdinitialization
  • forthinitialization

我希望这 4 个类按照 1、2、3、4 的顺序加载。

如下图,直接加载的话,顺序是 1、4、2、3,并不能达到要求。

如何控制

注意:网上很多文章说order注解或ordered接口可以控制 bean 的加载顺序,其是并不能,它们的作用是定义 spring ioc 容器中 bean 定义类的执行顺序的优先级,并不是定义加载顺序。

使用@dependson 注解

在需要调整顺序的类上依次加@dependson注解,缺点是类过多的时候需要一个个加注解,且不好维护

@component
public class firstinitialization {

    @postconstruct
    public void init(){
        system.out.println("我是第一个加载!");
    }

}
@component
@dependson("firstinitialization")
public class secondinitialization {

    @postconstruct
    public void init(){
        system.out.println("我是第二个加载!");
    }

}
@component
@dependson("secondinitialization")
public class thirdinitialization {

    @postconstruct
    public void init(){
        system.out.println("我是第三个加载!");
    }

}
@component
@dependson("thirdinitialization")
public class forthinitialization {

    @postconstruct
    public void init(){
        system.out.println("我是第四个加载!");
    }

}

执行结果如下

基于 applicationcontextinitializer 接口

接口简介

这里我简单介绍一个这个接口的用处, 等到整理到相关源码的时候再详细介绍。

applicationcontextinitializer接口是在 spring 容器刷新之前执行的一个回调函数。

执行时机:

spring 内部执行configurableapplicationcontext#refresh()方法前;

springboot 执行run()方法前。

一般有什么用呢?

在 springboot 应用中 classpath 上会有很多 jar 包,有些 jar 包需要在refresh()调用前对应用上下文做一些初始化动作,因此会提供applicationcontextinitializer接口的实现类,放在如下图的文件中,这样会被springapplication#initialize发现,然后完成对应初始化。

实现步骤

首先创建一个类继承applicationcontextinitializer接口。

public class myapplicationcontextinitializer implements applicationcontextinitializer {
    @override
    public void initialize(configurableapplicationcontext applicationcontext) {

        //将自定义的beanfactorypostprocessor实现类保存到applicationcontext中
        applicationcontext.addbeanfactorypostprocessor(new mybeanfactorypostprocessor());
    }
}

创建meta-inf/spring.factories文件。

自定义beandefinitionregistrypostprocessor

/**
 * beanfactorypostprocessor的子类
 * 允许开发人员在bean定义注册之前和之后对beandefinition进行自定义处理,例如添加,修改或删除bean定义等。
 */
public class mybeanfactorypostprocessor implements beandefinitionregistrypostprocessor {

    // 初始化需要排序的类,这里要保证插入顺序只能用linkedhashmap
    private static final map<string, class> order_bean_map = new linkedhashmap<>() {
        {
            put("firstinitialization", firstinitialization.class);
            put("secondinitialization", secondinitialization.class);
            put("thirdinitialization", thirdinitialization.class);
            put("forthinitialization", forthinitialization.class);
        }
    };

    @override
    public void postprocessbeandefinitionregistry(beandefinitionregistry registry) throws beansexception {
        optional.ofnullable(order_bean_map.keyset()).orelse(new hashset<>()).stream()
                .foreach(beanname -> {
                    // 初始化一个 bean 定义
                    abstractbeandefinition beandefinition = beandefinitionbuilder
                            .genericbeandefinition().getbeandefinition();

                    // 按顺序注册每个bean
                    beandefinition.setbeanclass(order_bean_map.get(beanname));
                    registry.registerbeandefinition(beanname, beandefinition);
                });
    }
}

执行结果如下

以上就是spring控制bean加载顺序的操作方法的详细内容,更多关于spring控制bean加载顺序的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com