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

    }

}

相关推荐
岁忧20 分钟前
(LeetCode 每日一题) 1865. 找出和为指定值的下标对 (哈希表)
java·c++·算法·leetcode·go·散列表
YuTaoShao23 分钟前
【LeetCode 热题 100】240. 搜索二维矩阵 II——排除法
java·算法·leetcode
考虑考虑1 小时前
JDK9中的dropWhile
java·后端·java ee
想躺平的咸鱼干1 小时前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
hqxstudying2 小时前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·2 小时前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
春生野草2 小时前
关于SpringMVC的整理
spring
Bug退退退1233 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠3 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
Zz_waiting.3 小时前
Javaweb - 10.4 ServletConfig 和 ServletContext
java·开发语言·前端·servlet·servletconfig·servletcontext·域对象