系列二十一、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);
        }

    }

}

相关推荐
ThetaarSofVenice10 分钟前
Java从入门到放弃 之 泛型
java·开发语言
嘟嘟Listing18 分钟前
jenkins docker记录
java·运维·jenkins
WHabcwu24 分钟前
统⼀异常处理
java·开发语言
zaim125 分钟前
计算机的错误计算(一百六十三)
java·c++·python·matlab·错数·等价算式
枫叶丹425 分钟前
【在Linux世界中追寻伟大的One Piece】多线程(一)
java·linux·运维
2401_8543910826 分钟前
Spring Boot OA:企业数字化转型的利器
java·spring boot·后端
山山而川粤33 分钟前
废品买卖回收管理系统|Java|SSM|Vue| 前后端分离
java·开发语言·后端·学习·mysql
武昌库里写JAVA35 分钟前
Vue3与Vue2 对比
spring boot·spring·毕业设计·layui·课程设计
栗豆包36 分钟前
w053基于web的宠物咖啡馆平台的设计与实现
java·struts·spring·tomcat·maven·intellij-idea
weixin_446707741 小时前
IDEA2024 maven构建跳过测试
java·maven