目录
- 前言
- 例子代码和bean顺序
- 改变全注解类加载顺序
- bean 的依赖关系改变,被依赖的先加载
- 自定义BeanFactoryPostProssort 提前获取某个bean
- 按照refresh的finishBeanFactoryInitialization方法改变bean
- BeanDefinitionRegistryPostProcessor改变beanDefinitions
- @Configuration下@Bean从上到下的顺序
- 实现ImportBeanDefinitionRegistrar接口自己注册
- todo
前言
https://doctording.blog.csdn.net/article/details/144865082, 在认识AnnotationConfigApplicationContext加载流程的时候,实际上涉及到了一些顺序
- BeanFactoryPostProcessor 是优先加载的,且有一系列顺序
观察refresh()方法的org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
,可以看到普通bean加载是有一定顺序的, 如下
/*** Finish the initialization of this context's bean factory,* initializing all remaining singleton beans.*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.beanFactory.preInstantiateSingletons();
}
beanFactory.preInstantiateSingletons();
按照beanDefinitions顺序加载
例子代码和bean顺序
如下定义两个@Configuration类,分别扫描不同的package
默认输出如下:
- 两个全注解类的bean先加载
- 然后分别是扫描各自扫描出来的bean的默认顺序加载
改变全注解类加载顺序
输出如下,符合预期
bean 的依赖关系改变,被依赖的先加载
- depensOn
@Service
@DependsOn(value = "PBean2")
public class PBean1 {public PBean1() {System.out.println("PBean1");}
}
- 构造函数注入
@Service
public class QBean1 {public QBean1(QBean2 qBean2) {System.out.println("QBean1:" + qBean2);}
}
如下:
自定义BeanFactoryPostProssort 提前获取某个bean
@Service
public class SelfBfpp implements BeanFactoryPostProcessor {public SelfBfpp() {System.out.println("SelfBfpp");}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {beanFactory.getBean("PBean2");}
}
按照refresh的finishBeanFactoryInitialization方法改变bean
例如实现了LoadTimeWeaverAware的bean先加载
补充:LoadTimeWeaverAware实际却是没碰到过,是Spring中用于在类加载时对指定的类型进行增强的工具,通常用于AspectJ的AOP实现。
BeanDefinitionRegistryPostProcessor改变beanDefinitions
-
如下,直接不加载某个bean了
-
怪异的处理,然某个bean最后加载了
@Configuration下@Bean从上到下的顺序
实现ImportBeanDefinitionRegistrar接口自己注册
全注解类加上@Import
@EnableAspectJAutoProxy
@Configuration
@ComponentScan("com.aop.order.p2")
@Import(SelfRegistor.class)
public class ConfigB {public ConfigB() {System.out.println("ConfigB");}}
然后自己注册,确保顺序
public class SelfRegistor implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {BeanDefinition beanDefinition4 = new GenericBeanDefinition();((GenericBeanDefinition) beanDefinition4).setBeanClass(QBean4.class);registry.registerBeanDefinition("q4", beanDefinition4);BeanDefinition beanDefinition3 = new GenericBeanDefinition();((GenericBeanDefinition) beanDefinition3).setBeanClass(QBean3.class);registry.registerBeanDefinition("q3", beanDefinition3);}
}
如下输出,先4后3