一、概述
我们知道启动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
<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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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);
}
}
}