四时宝库

程序员的知识宝库

Spring-IOC(三)(springioc三级缓存)

invokeBeanFactoryPostProcessors

这个方法是spring对外扩展的最重要的功能之一,在实现BeanFactoryPostProcessor接口的方法中可以对bean进行修改。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

getBeanFactoryPostProcessors()方法获取的是程序员自己手动添加的BeanFactoryPostProcessor实现类,这个手动添加不是写一个实现类再加个@Component注解,这个属于spring注入的bean,真正的写法如下:

public class RunTest {

   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.addBeanFactoryPostProcessor(new MultiBeanFactoryPostProcessor());
      context.register(AppConfig.class);
      context.refresh();
      System.out.println(context.getBean("serviceImpl"));
   }
}

Spring-IOC(一)中的写法是将AppCong.class放在AnnotationConfigApplicationContext构造方法中,现在需要将它拿出来单独注册。这样进入getBeanFactoryPostProcessos方法时就可以看到我们手动添加的processor。

invokeBeanFactoryPostProcessors

在说这个方法之前,先说下ConfigurationClassPostProcessor类,这个类实现了BeanDefinitionRegistryPostProcessor接口,BeanDefinitionRegistryPostProcessor接口实现了BeanFactoryPostProcessor。在invokeBeanFactoryPostProcessors方法中会先执行BeanDefinitionRegistryPostProcessor接口中的方法再执行BeanFactoryPostProcessor接口中的方法。

BeanDefinitionRegistryPostProcessor是我们自定义的添加更多的beanDefinition。

ConfigurationClassPostProcessor这个类是spring自己添加的,这个类就是解析各种注解,将注解对应类添加到beanDefinitionMap中。

for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			...
}
  • 这个beanFactoryPostProcessors是我们手动添加的,这里没有,就先跳过
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
      beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
   if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
      currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
      processedBeans.add(ppName);
   }
}
sortPostProcessors(currentRegistryProcessors, beanFactory);

registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
  • 组装processor并调用

上面几步是将BeanDefinitionRegistryPostProcessor接口的实现类添加到currentRegistryProcessors中,然后循环调用;还有一步是将currentRegistryProcessors集合放入registryProcessors中,是为了后续的BeanFactoryPostProcessor接口的调用。

  • invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
      Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

   for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanDefinitionRegistry(registry);
   }
}

这块代码很简单就是循环调用BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法,通过上述知道这里只有一个processor:ConfigurationClassPostProcessor

  • ConfigurationClassPostProcessor

跟踪代码最终会进入方法:ConfigurationClassPostProcessor#processConfigBeanDefinitions

这个方法主要做了三件事:

①:从容器中获取和@Configuration注解相关的类

List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
   BeanDefinition beanDef = registry.getBeanDefinition(beanName);
   if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
         ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
      if (logger.isDebugEnabled()) {
         logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
      }
   }
   else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
      configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
   }
}
if (configCandidates.isEmpty()) {
   return;
}

从registry中获取BeanDefinitionName,这些beanDefinitionName是在AnnotationConfigApplicationContext中spring自己添加的几个beanDefinition,还有一个扫描出我们传入的AppConfig类,其中只有AppConfig类上添加了注解:@ComponentScan

看下isFullConfigurationClass和isLiteConfigurationClass两个是什么意思,因为后续还会用到这个,所以要在这里搞清楚才可以。

private static final String CONFIGURATION_CLASS_FULL = "full";
private static final String CONFIGURATION_CLASS_LITE = "lite";

full和lite直接是用字符串表示的,在for循环中,AppConfig第一次进来肯定既没有full标志,也没有lite标志,所以就会进入else if逻辑:ConfigurationClassUtils#checkConfigurationClassCandidate

在该方法中有这么一段逻辑:

if (isFullConfigurationCandidate(metadata)) {
   beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}else if (isLiteConfigurationCandidate(metadata)) {
   beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}else {
   return false;
}

再次判断是full还是lite,这里的判断才有意义:

isFullConfigurationCandidate:

public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
   return metadata.isAnnotated(Configuration.class.getName());
}

如果含有Configuration注解的类是属于full。

isLiteConfigurationCandidate:

public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
   // Do not consider an interface or an annotation...
   if (metadata.isInterface()) {
      return false;
   }
   // Any of the typical annotations found?
   for (String indicator : candidateIndicators) {
      if (metadata.isAnnotated(indicator)) {
         return true;
      }
   }
   // Finally, let's look for @Bean methods...
   try {
      return metadata.hasAnnotatedMethods(Bean.class.getName());
   }
   catch (Throwable ex) {
      if (logger.isDebugEnabled()) {
         logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
      }
      return false;
   }
}

判断是否是lite:

1)如果是接口直接返回false

2)如果含有Component、ComponentScan、Import、ImportResource四个注解中的其中一个说明是lite(AppConfig含有ComponentScan注解,所以属于lite)

3)如果以上两者都不是就判断是否有Bean注解

判断完full和lite之后将对应的beanDefinition放入configCandidates中

判断configCandidates是否为空,如果为空,方法结束。

通过以上所有的判断,最后configCandidates中只有我们自己写的AppConfig

②:解析这些类

ConfigurationClassParser parser = new ConfigurationClassParser(
      this.metadataReaderFactory, this.problemReporter, this.environment,
      this.resourceLoader, this.componentScanBeanNameGenerator, registry);

parser.parse(candidates);

跟踪代码进入方法:

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
   processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}

		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					existingClass.mergeImportedBy(configClass);
				}
				// Otherwise ignore new imported config class; existing non-imported class overrides it.
				return;
			}
			else {
				// Explicit bean definition found, probably replacing an import.
				// Let's remove the old one and go with the new one.
				this.configurationClasses.remove(configClass);
				this.knownSuperclasses.values().removeIf(configClass::equals);
			}
		}

		// Recursively process the configuration class and its superclass hierarchy.
		SourceClass sourceClass = asSourceClass(configClass);
		do {
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}

上面的代码最主要的是在do while循环。首先将configClass转换成SourceClass,然后开始处理这个类。

1)首先判断是否含有Component注解,如果有,则处理Component注解相关的类

// 由于 @Configuration 注解上有 @Component 注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
   // Recursively process any member (nested) classes first
   // 首先递归处理嵌套类,这个是为了防止在含有@Component的类中还有内部类含有@Component注解
   processMemberClasses(configClass, sourceClass);
}

这些处理先放着,后面会一起整理

2)判断是否含有PropertySources注解

// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
      sourceClass.getMetadata(), PropertySources.class,
      org.springframework.context.annotation.PropertySource.class)) {
   if (this.environment instanceof ConfigurableEnvironment) {
      processPropertySource(propertySource);
   }
   else {
      logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
            "]. Reason: Environment must implement ConfigurableEnvironment");
   }
}

3)判断是否含有ComponentScans或者ComponentScan注解

Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
      sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
      !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
   for (AnnotationAttributes componentScan : componentScans) {
      // The config class is annotated with @ComponentScan -> perform the scan immediately
      // 此处就是解析@ComponentScan中包名下的所有加了spring注解的类,并放入转换成beanDefinition
      Set<BeanDefinitionHolder> scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
      // Check the set of scanned definitions for any further config classes and parse recursively if needed
      for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
         BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
         if (bdCand == null) {
            bdCand = holder.getBeanDefinition();
         }
         // 此处是检查扫描出来的类是否加了@Configuration 注解
         if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
            parse(bdCand.getBeanClassName(), holder.getBeanName());
         }
      }
   }
}

4)处理还有Import注解的类

// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);

5)判断是否含有ImportResource注解的类

// Process any @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);
   }
}

6)处理Bean注解

// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
   configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

7)处理接口默认方法

// Process default methods on interfaces
processInterfaces(configClass, sourceClass);

8)处理父类

// Process superclass, if any
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();
   }
}

③:加载bean定义信息,主要是将@Bean,@Configuration,@Import,@ImportSource,@ImportRegistry注解相关的类放入beanDefinitionMap中

对第二步解析出来的类进行校验,然后放入beanDefinitionMap中

parser.validate();

Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);

// Read the model and create bean definitions based on its content
// 3.加载bean定义信息,主要是将@Bean,@Configuration,@Import,@ImportResource,@ImportRegistry注册为bean
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);

candidates.clear();

以上就是ConfigurationClassPostProcessor类的所有处理逻辑,这个功能处理完了就开始处理refresh方法的后续步骤。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接