目录
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, List beanFactoryPostProcessors) {
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, Predicate filter)
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 Set doScan(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 解析流程
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)