Spring5源码 - 04 invokeBeanFactoryPostProcessors 源码解读_1
Spring5源码 - 05 invokeBeanFactoryPostProcessors 源码解读_2
前两篇博文 我们过了一下这个方法的主干流程,其中有个关键的方法,我们没有细说就是这个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);
我们重点关注第三步 和第四步
先看第三步
所以重点看
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; }
第三步完成了,我们来看下这一步Spring是如和把配置类注册到容器中的
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); //注册我们的配置类到容器中 for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } }
那自然就是
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
很清晰哈
一个个的看下吧
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可以跟的各种属性
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的。
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) { registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry)); }
很直观了哈 ,循环直接调用ImportBeanDefinitionRegistrar.registerBeanDefinitions方法进行beanDefinition的注册。