目录
1、后置PostProcess的调用
2、ConfigurationClassPostProcessor后置处理器解析
3、@Configuration注解加与不加的区别
4、重复beanName的覆盖原则
1、后置PostProcess的调用
后置处理器在 new AnnotatedBeanDefinitionReader() 时加载,在 register(componentClasses) 中注册,在 refresh() 方法中被调用
public AnnotationConfigApplicationContext(Class>... componentClasses) {
// 1-生成三大组件:BeanFactory、BeanDefinitionReader、BeanDefinitionScanner
this();
// 2-注册BeanDefinition——>registerBeanDefinition
register(componentClasses);
// 3-Spring重点->Bean生命周期的实现
refresh();
}
在 refresh() 方法中 invokeBeanFactoryPostProcessors(beanFactory) 真正调用后置处理器
其过程图如下:
后置处理器的加载流程代码:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors) { Set processedBeans = new HashSet<>(); // 1-首先调用BeanDefinitionRegistryPostProcessor的后置处理器 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List regularPostProcessors = new ArrayList<>(); List registryProcessors = new ArrayList<>(); // beanFactoryPostProcessors ->内容需要手动添加,一般为空 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } // 不要在这里初始化FactoryBeans:我们需要让所有常规bean保持未初始化状态,以便让bean factory后处理器应用于它们! // 在实现PriorityOrdered、Ordered和其他功能的BeanDefinitionRegistryPostProcessor之间进行分离。 List currentRegistryProcessors = new ArrayList<>(); // 首先,调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 判断是否实现了PriorityOrdered接口 ->优先调用 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // beanFactory.getBean进行实例化 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } // (1)对PostProcessors进行排序 sortPostProcessors(currentRegistryProcessors, beanFactory); // (2)汇总PostProcessors registryProcessors.addAll(currentRegistryProcessors); // (3)调用PostProcessors invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 接下来,调用实现了Ordered接口的BeanDefinitionRegistryPostProcessors postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 排除processedBeans中已经调用的PostProcessors if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 最后,调用所有其他的BeanDefinitionRegistryPostProcessors boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 排除在之前两次processedBeans中已经调用的PostProcessors if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // 调用实现了BeanDefinitionRegistryPostProcessor的接口,同时也实现了BeanFactoryPostProcessor的方法 // ConfigurationAnnotationProcessor 在这里会被再次调用 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); // 手动定义部分的BeanFactoryPostProcessors ->regularPostProcessors invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. // 2-当前的beanFactory没有实现BeanDefinitionRegistry 直接调用 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // 省略大段代码... }
2、ConfigurationClassPostProcessor后置处理器解析
ConfigurationClassPostProcessor后置处理器会被优先加载,因为ConfigurationClassPostProcessor 同时实现了 BeanDefinitionRegistry 和 PriorityOrdered 两个接口,该类的继承关系图如下:
ConfigurationClassPostProcessor后置处理器加载流程图
doProcessConfigurationClass()源码如下:
protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter) throws IOException { if (configClass.getMetadata().isAnnotated(Component.class.getName())) { processMemberClasses(configClass, sourceClass, filter); } // 处理@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.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // 处理@ComponentScan注解 Set 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) { // The config class is annotated with @ComponentScan -> perform(执行) the scan immediately(立即进行扫描) Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // 检查扫描的定义集是否有任何进一步的配置类,并在需要时进行递归解析 for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // 处理 @Import annotations processImports(configClass, sourceClass, getImports(sourceClass), filter, 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 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); return sourceClass.getSuperClass(); } } return null; }
扫描和注册源码
protected SetdoScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); // 创建beanDefinitions用于保存扫描后生成的bean定义对象 Set beanDefinitions = new LinkedHashSet<>(); // 循环包路径集合 for (String basePackage : basePackages) { // 找到候选的Components->真正的扫描和加载内容 Set candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); // 处理@Autowire注解相关 if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } // 把解析出来的组件bean定义注册到IOC容器中 if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); // 注册 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
到此,整个ConfigurationClassPostProcessor后置处理器的大致流程就介绍完了,当中还有很多处理细节,可以参照整个流程再详细拆分和解读。
3、@Configuration注解加与不加的区别
在项目中,通常都会配置一个或者多个加了@Configuration注解的配置类,那么@Configuration这个注解有什么用呢?
public class MyConfig {
@Bean("person")
public Person getPersonInstance(){
return new Person("XiaoHong", "女", getWoMenInstance());
}
@Bean("woMen")
public WoMen getWoMenInstance(){
return new WoMen();
}
}
执行下边的代码,会发现当不加@Configuration注解时,Person、WoMen 两个类还是会被实例化,spring环境也可以正常运行,但是WoMen 被实例化了两次。
public class MainStat {
public static void main(String[] args) {
//加载配置文件,生产Bean
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
}
}
给MyConfig加上@Configuration注解后,查看执行结果
@Configuration // 如果不加@Configuration,WoMen会实例化两次
public class MyConfig {
@Bean("person")
public Person getPersonInstance(){
return new Person("XiaoHong", "女", getWoMenInstance());
}
@Bean("woMen")
public WoMen getWoMenInstance(){
return new WoMen();
}
}
总结:当不加@Configuration注解的时候,WoMen会被实例化两次,这违背了spring默认单例的设计原则,当加上@Configuration注解的时候,WoMen只被实例化了一次。
源码分析:
当Spring解析MyConfig的时候,会给它的一个属性标识为Full,表明它是一个全注解类。
然后在我们调用ConfigurationClassPostProcessor.postProcessBeanFactory()方法的时候会去判断bean工厂当中是否有bean需要进行cglib代理。
在ConfigurationClassPostProcessor.enhanceConfigurationClasses()方法中
Cglib代理主要是对自定义的方法进行拦截增强;当执行MyConfig中的方法的时候会去执行Cglib代理类中的代理方法,主要就是CallBacks中的方法。
在 BeanMethodInterceptor.intercept()方法中
isCurrentlyInvokedFactoryMethod(beanMethod)) 会判断给定的方法和正在调用方法是否相同;如果相同就调用父类的方法进行new(当前Bean正是需要去创建的Bean);如果不同就调用beanFactory.getBean()获取(先从IOC容器中去获取,避免重复创建)。
总结:加上@Configuration注解,Spring给类加上了Cglib代理。在执行配置类的方法时,会执行Cglib代理类中的方法,其中有一个非常重要的判断,当给定的方法和正在调用的方法是同一个方法时,会执行父类的方法new一个新的实例(Cglib代理基于继承);当给定的方法和正在调用的方法不是同一个方法时,会先调用beanFactory.getBean获取。
4、重复beanName的覆盖原则
(1)如果在同一个@ComponentScan下有相同名称的Bean,那么Spring会报错
如,把以下两个类都声明为"person",都是通过@ComponentScan来解析@Component注解,那么启动Spring时会报错
@Component("person")
@ComponentScan("com.swadian.task")
public class Person {
private String name;
private String sex;
}
@Component("person")
@ComponentScan("com.swadian.task")
public class WoMen {
private String name;
private int age;
}
启动Spring,会报如下错误
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'person' for bean class [com.swadian.task.WoMen] conflicts with existing, non-compatible bean definition of same name and class [com.swadian.task.Person]
(2)如果通过@Component注解定义一个Bean,然后通过Java配置类(@Configuration类)注解@Bean定义一个相同名称的Bean,那么@Bean定义的Bean最终会覆盖@Component注解定义的同名Bean。
@Component
public class Person {
private String name;
private String sex;
}
以上Bean定义最终会被@Configuration类中的同名Bean定义覆盖
@Configuration
public class MyConfig {
@Bean("person") // 最终覆盖@Component定义的同名Bean
public Person getPersonInstance(){
return new Person();
}
}
原因:@ComponentScan注解先会被解析,@Bean注解后解析,所以后者会覆盖前者,在Spring中Bean定义是默认可以覆盖的
ConfigurationClassPostProcessor 解析流程



