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方法的后续步骤。