一、概述
我们知道启动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!");}@Beanpublic 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 {@Overridepublic 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);}}}