系列二十一、Spring中bean的创建顺序

一、概述

我们知道启动IOC容器时,Spring会为我们创建各种各样的bean,那么思考一个问题,bean的创建顺序是由什么决定的呢?答:bean的创建顺序是由BeanDefinition的注册信息决定的,这个其实很好理解,bean创建完成的标识是循环完所有的BeanDefinition,关于BeanDefinition的加载过程,请参考 系列十五、BeanDefinition ,关于bean创建完成的标识请参考 系列十六、Spring IOC容器的扩展点 #2.4

二、BeanDefinition的注册顺序

2.1、规则

BeanDefinition的注册顺序是由注解的解析顺序决定的,规则如下:

@Configuration > @Component > @Import(普通bean) > @Bean > @Import(xxxImportBeanDefinitionRegistrar)

2.2、案例

2.2.1、pom.xml

XML 复制代码
<dependencies>
	<!--spring基本依赖-->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-aop</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-beans</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-expression</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>

	<!-- 数据源 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>8.0.26</version>
	</dependency>
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>1.2.16</version>
	</dependency>

	<!-- 普通maven项目中使用Sl4j注解 -->
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.22</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-api</artifactId>
		<version>1.7.32</version>
	</dependency>
	<dependency>
		<groupId>ch.qos.logback</groupId>
		<artifactId>logback-classic</artifactId>
		<version>1.2.10</version>
	</dependency>

	<!-- aop -->
	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>3.1</version>
	</dependency>
	<dependency>
		<groupId>aopalliance</groupId>
		<artifactId>aopalliance</artifactId>
		<version>1.0</version>
	</dependency>
	<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>1.9.19</version>
	</dependency>

	<!-- 工具 -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.13.2</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>fastjson</artifactId>
		<version>1.2.76</version>
	</dependency>
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-collections4</artifactId>
		<version>4.3</version>
	</dependency>
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-lang3</artifactId>
		<version>3.11</version>
	</dependency>
	<dependency>
		<groupId>cn.hutool</groupId>
		<artifactId>hutool-all</artifactId>
		<version>5.7.22</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.12.1</version>
	</dependency>
	<dependency>
		<groupId>commons-logging</groupId>
		<artifactId>commons-logging</artifactId>
		<version>1.1.1</version>
	</dependency>

</dependencies>

2.2.2、MySpringConfig

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:18
 * @Description:
 */
@ComponentScan(basePackages = {"org.star"})
@Configuration
@Import({ComponentB.class})
@EnableCustomBean
public class MySpringConfig {

    public MySpringConfig() {
        System.out.println("MySpringConfig's NoArgsConstructor was invoked!");
    }

    @Bean
    public ComponentC componentC() {
        return new ComponentC();
    }

}

2.2.3、ComponentA

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:21
 * @Description:
 */
@Component
public class ComponentA {

    public ComponentA() {
        System.out.println("ComponentA's NoArgsConstructor was invoked!");
    }

}

2.2.4、ComponentB

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:21
 * @Description:
 */
public class ComponentB {

    public ComponentB() {
        System.out.println("ComponentB's NoArgsConstructor was invoked!");
    }

}

2.2.5、ComponentC

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:21
 * @Description:
 */
public class ComponentC {

    public ComponentC() {
        System.out.println("ComponentC's NoArgsConstructor was invoked!");
    }

}

2.2.6、ComponentD

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:21
 * @Description:
 */
@Data
public class ComponentD {

    private String name;
    private String description;

    public ComponentD() {
        System.out.println("ComponentD's NoArgsConstructor was invoked!");
    }

}

2.2.7、MyImportBeanDefinitionRegistrar

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:26
 * @Description:
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(ComponentD.class);

        // 添加属性
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        propertyValues.add("name","ComponentD");
        propertyValues.add("description","组件D");
        beanDefinition.setPropertyValues(propertyValues);

        // 注入到Spring容器中
        registry.registerBeanDefinition("componentD",beanDefinition);

    }

}

2.2.8、EnableCustomBean

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:40
 * @Description:
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MyImportBeanDefinitionRegistrar.class)
public @interface EnableCustomBean {

}

2.2.9、SpringBeanCreateOrderMainApp

java 复制代码
/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/27 14:33
 * @Description:
 */
public class SpringBeanCreateOrderMainApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

    }

}

相关推荐
SL_staff13 分钟前
别急着买商业规则引擎:90%风控场景根本不需要全量编码能力
java·程序员·groovy
ManageEngineITSM32 分钟前
DevOps和ITIL是什么关系?是替代还是互补一文讲清
java·服务器·资产管理·变更管理
SL_staff1 小时前
ERP排程总在纸上谈兵?JVS-APS如何用真实产能约束打通计划与执行闭环
java·人工智能·开源
xcl09251 小时前
24小时自助健身房系统软件开发实战指南:从架构到部署
java·spring boot
码少女2 小时前
Linux--多路转接之select
java·服务器·数据库
nvvas3 小时前
Java 入门(四):数组——数据的集合管理
java·开发语言
Lambert2813 小时前
AgentScope Java 从零(07):官方有权限引擎,我却在工具里写了个 if
java·后端·ai编程
Kyrie_kk3 小时前
Java--ThreadLocal线程副本(一)
java·后端
君顾14 小时前
本地城市低空经济管理系统定制:城市级低空运营平台架构与落地实战
java·开发语言·飞手
奈斯先生Vector4 小时前
当模型版本不断变化,RelayRouter 能否帮助 AI 应用摆脱深度绑定
android·java·人工智能·开源·aigc