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

    }

}

相关推荐
2401_857439697 分钟前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧6668 分钟前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
李老头探索10 分钟前
Java面试之Java中实现多线程有几种方法
java·开发语言·面试
芒果披萨16 分钟前
Filter和Listener
java·filter
qq_49244844620 分钟前
Java实现App自动化(Appium Demo)
java
阿华的代码王国29 分钟前
【SpringMVC】——Cookie和Session机制
java·后端·spring·cookie·session·会话
找了一圈尾巴1 小时前
前后端交互通用排序策略
java·交互
哎呦没3 小时前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
m0_571957585 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
魔道不误砍柴功7 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python