文章目录
Pre
Spring5源码 - 04 invokeBeanFactoryPostProcessors 源码解读_1
Spring5源码 - 05 invokeBeanFactoryPostProcessors 源码解读_2
细说invokeBeanDefinitionRegistryPostProcessors
前两篇博文 我们过了一下这个方法的主干流程,其中有个关键的方法,我们没有细说就是这个invokeBeanDefinitionRegistryPostProcessors。
这个方法很重要,本篇博文我们就一起来剖析下。
话不多说,还是下来梳理主干流程,然后再对着源码过一遍
流程图
我们来看流程图
源码分析
我们从头跟一下
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
进入到AnnotationConfigApplicationContext的构造函数中
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//调用构造函数
this();
//注册我们的配置类
register(annotatedClasses);
//IOC容器刷新接口
refresh();
}
这里我们关注refresh方法,这个方法太重要了,里面非常深的调用链,我们这里先有个大概的认知
@Override
public void refresh() throws BeansException, IllegalStateException {
//1:准备刷新上下文环境
prepareRefresh();
//2:获取告诉子类初始化Bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3:对bean工厂进行填充属性
prepareBeanFactory(beanFactory);
try {
// 第四:留个子类去实现该接口
postProcessBeanFactory(beanFactory);
// 调用我们的bean工厂的后置处理器.
invokeBeanFactoryPostProcessors(beanFactory);
// 调用我们bean的后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化国际化资源处理器.
initMessageSource();
// 创建事件多播器
initApplicationEventMulticaster();
// 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomat的.
onRefresh();
//把我们的事件监听器注册到多播器上
registerListeners();
//实例化我们剩余的单实例bean.
finishBeanFactoryInitialization(beanFactory);
// 最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)
finishRefresh();
}
}
我们先重点关注【invokeBeanFactoryPostProcessors(beanFactory);
】
跟进去,重点看 invokeBeanFactoryPostProcessors
//传入bean工厂和获取applicationContext中的bean工厂后置处理器(但是由于没有任何实例化过程,所以传递进来的为空)
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
继续,重点关注
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
这个方法就是我们今天要研究的源码
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
//获取容器中的ConfigurationClassPostProcessor的后置处理器进行bean定义的扫描
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
这里就一个,那就是 ConfigurationClassPostProcessor
仅需跟进去 ,看ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
方法
//真正的解析我们的bean定义
processConfigBeanDefinitions(registry);
这个方法主要干的三件事儿
- 找到开发人员传入主配置类
- 创建一个配置类解析器对象
- 解析我们的配置类
parser.parse(candidates);
- 把解析出来的配置类注册到容器中
this.reader.loadBeanDefinitions(configClasses);
我们重点关注第三步 和第四步
先看第三步
解析配置类 parser.parse(candidates)
所以重点看
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
跟进去
/**
* 真的解析我们的配置类
* @param metadata 配置类的源信息
* @param beanName 当前配置类的beanName
* @throws IOException
*/
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
/**
* 第一步:把我们的配置类源信息和beanName包装成一个ConfigurationClass 对象
*/
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
进入
关注
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
这里面就是处理各种注解【@propertySource、@ComponentScan 、@Import、@ImportResource、@Bean】的地方,我们来看下源码
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
//处理我们的@propertySource注解的
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
//解析我们的 @ComponentScan 注解
//从我们的配置类上解析处ComponentScans的对象集合属性
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
//循环解析 我们解析出来的AnnotationAttributes
for (AnnotationAttributes componentScan : componentScans) {
//把我们扫描出来的类变为bean定义的集合 真正的解析
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
//循环处理我们包扫描出来的bean定义
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//判断当前扫描出来的bean定义是不是一个配置类,若是的话 直接进行递归解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
//递归解析
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 处理 @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 处理 @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 处理 @Bean methods 获取到我们配置类中所有标注了@Bean的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理配置类接口的
processInterfaces(configClass, sourceClass);
// 处理配置类的父类的
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// 没有父类解析完成
return null;
}
配置类注册到容器中 this.reader.loadBeanDefinitions(configClasses)
第三步完成了,我们来看下这一步Spring是如和把配置类注册到容器中的
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
//注册我们的配置类到容器中
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
那自然就是
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
很清晰哈
一个个的看下吧
注册@Import的bean
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
//获取我们的配置类的源信息
AnnotationMetadata metadata = configClass.getMetadata();
//构建为我们的bean定义
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
//设置他的scope
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
//获取bean的名称
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
//处理我们的JRS250组件的
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注册我们的bean定义到我们的容器中
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isDebugEnabled()) {
logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}
}
重点就是
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
注册@Bean的bean
处理@Bean可以跟的各种属性
注册@ImportResources的bean
private void loadBeanDefinitionsFromImportedResources(
Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
// reader实例缓存
Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();
// 循环处理<配置文件路径-reader>
importedResources.forEach((resource, readerClass) -> {
// 如果注解配置的Reader是默认的(我们一般其实也不改)
if (BeanDefinitionReader.class == readerClass) {
if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
// 如果文件名是.groovy结尾,则使用GroovyBeanDefinitionReader
// 说实话我也第一次知道还可以用groovy脚本来做spring的配置文件
// 后面我去看了一下BeanDefinitionReader这个接口的实现类,发现还一个
// PropertiesBeanDefinitionReader,感兴趣的同学可以去研究一下
readerClass = GroovyBeanDefinitionReader.class;
}
else {
// 默认情况下我们使用XmlBeanDefinitionReader
readerClass = XmlBeanDefinitionReader.class;
}
}
// 先从缓存拿
BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
if (reader == null) {
try {
// 拿不到就新建一个,配置的reader类必须有一个只有BeanDefinitionRegistry参数的构造器
reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
// Delegate the current ResourceLoader to it if possible
if (reader instanceof AbstractBeanDefinitionReader) {
AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
abdr.setResourceLoader(this.resourceLoader);
abdr.setEnvironment(this.environment);
}
readerInstanceCache.put(readerClass, reader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
}
}
// 使用reader从文件加载bean
reader.loadBeanDefinitions(resource);
});
}
默认情况下 是创建一个XmlBeanDefinitionReader来解析加载我们的配置文件中定义的bean的。
注册ImportBeanDefinition的bean
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, this.registry));
}
很直观了哈 ,循环直接调用ImportBeanDefinitionRegistrar.registerBeanDefinitions方法进行beanDefinition的注册。