一. 前言
在这三篇文章以Java Config的启动方式系统的梳理了Spring在启动过程的源码解析。
Spring源码系列——容器的启动过程(一)
在这个过程中,见识了Spring当中的很多思想以及核心组件的使用。本篇文章将系统解析Spring后置处理器当中最核心的处理器之一: ConfigurationClassPostProcessor
二. UML类图
ConfigurationClassPostProcessor
的UML类图如下:
从UML类图中可以发现: ConfigurationClassPostProcessor
实现了Aware接口,这意味着它不受Spring的生命周期管理,所以正常情况下开发者无法插足它的使用.只有Spring内部才能使用它. 最重要的是它实现了 BeanDefinitionRegistryPostProcessor
和 BeanFactoryPostProcessor
这两个接口. 在Spring源码系列——容器的启动过程(三) 中详细阐述了这两个接口之间的关系以及执行的优先级.这里不再赘述.
三. 代码入口
配置类
package com.leon.funddatahouse.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author created by leon on 2020-09-13
* @since 版本号
*/
@Configuration
@ComponentScan("com.leon.funddatahouse.spring")
public class Config {
}
复制代码
入口
package com.leon.funddatahouse.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author created by leon on 2020-09-13
* @since 版本号
*/
public class MyApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class);
}
}
复制代码
四. 源码解析
如何执行到ConfigurationClassPostProcessor
在Spring源码系列——容器的启动过程(三) 有详细介绍, 这里不再赘述. 由于ConfigurationClassPostProcessor
实现了BeanDefinitionRegistryPostProcessor
,因此:
先执行 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
再执行BeanFactoryPostProcessor#postProcessBeanFactory
4.1 postProcessBeanDefinitionRegistry() 源码解析
源码如下:
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
// 上面的代码都不重要,主要看这里.该方法才是核心方法
processConfigBeanDefinitions(registry);
}
复制代码
4.1.1 processConfigBeanDefinitions()才是核心
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 用于盛放解析出来的config类的bdh
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 从容器中获取所有bd name,在这里获取到的只有7个(Spring内部6个,自己的配置类1个.)
String[] candidateNames = registry.getBeanDefinitionNames();
// 循环遍历, 不放过任何一个符合条件的bd(实际上只有自己的配置类符合条件)
for (String beanName : candidateNames) {
// 根据beanName获取bd
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 判断是否已经被判定为configurationClass.
// 从ConfigurationClassUtils类可知,如果是判断是否是configurationClass的话,该属性不为空.
// 而刚进入到这里时,其属性一定为空,因此会走else if分支进一步判断
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 校验当前beanDef是否符合config候选条件. 具体如下:
// 1.如果有@Configuration注解,则为deanDef添加属性 CONFIGURATION_CLASS_FULL,表示是一个完全配置类.
// 2.如果没有@Configuration但是有@Bean/@Import等注解,则为beanDef添加属性 CONFIGURATION_CLASS_LITE,表示是一个简单的配置类.
// 3.以上两点只要满足一点,就会返回true,如果二者都没有,则返回false
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 经过遍历判断之后, 如果候选集合为空,则直接返回.
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
// 根据排序的值进行排序. 从UML类图可以得知,它实现了 @Ordered接口
// 题外话: 排序值的设置可以通过@Order设置也可通过实现Ordered接口或者PriorityOrdered接口重写getOrder来实现
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// 确定 bean name生成器, 简单,继续往下
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
// 设置environment, 简单, 继续往下.
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 创建@Configuration 的解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 将所有待解析的数组放在set集合中,达到去重的目的
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 将解析完成的beanDef放在这个集合中
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
// 递归解析 重要!!!
// 采用do...while的方式, 因为在解析的过程中,可能会发现新的需要解析的@Configuration class.
// 比如在解析出来的bean当中也有打上@Configuration注解的.这时需要重新比较所有的beanDef和已解析的beanDef来筛选出
// 新发现的Configuration class,并将其添加到候选集合中, 这样while的判断成立,将会进行新的一轮解析.
// 周而复始,直到将所有的@Configuration class解析完.
// 完成这一切的关键就在于解析器的parse方法!
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
复制代码
4.1.2 ConfigurationClassParser#parse()方法源码解析
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 循环遍历候选者
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
// 这里将根据BeanDefinition的具体类型来选择具体的解析方法.
// 在这里, Config.class是是通过注解的方式, 因此进入if分支.
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
} else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this.deferredImportSelectorHandler.process();
}
// ------------------分割线-----------------------
// 实际调用的重载版本是这个:
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
// 继续委托
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
// ------------------分割线-----------------------
// 核心方法
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 根据条件解析器来判断当前的configClass是否需要跳过解析
// 在这里Config.class不需要跳过解析, 因此if分支
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
// 判断是否是正在解析的config class, 如果是,则直接返回
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
// 这里判断是是否有@Import
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);
}
}
// 递归解析. 重要!!!
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
复制代码
4.1.3 doProcessConfigurationClass()源码解析
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// 判断是否有@Component注解. @Configuration注解嵌套了@Component注解,因此进入if分支进行处理.
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processMemberClasses(configClass, sourceClass);
}
// 处理解析@PropertySource和@PropertySources.
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<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
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();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 处理解析 @Import
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 处理解析 @ImportResource
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
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理接口上的默认方法,将其加到bd的beanMethods中
processInterfaces(configClass, sourceClass);
// 如果有父类,则返回父类Class,上一层方法会进行递归处理
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();
}
}
// No superclass -> processing is complete
return null;
}
复制代码
从这里可以看出,如果配置类上使用了@Configuration注解,那么Spring会将@ComponentScan
/ @Import/@Bean
/ @PropertySource
/ @ImportResource
等一并解析,(如果加了这些注解的话). 我们知道,@ComponentScan
等注解都是Spring 当中的基本且重要的"配置类型"的注解. 这里就说明了为什么@Configration注解时,deanDef的属性值为 ConfigurationClassUtils.CONFIGURATION_CLASS_FULL
,这说明它可以被当做是一个"完全"配置类来解析. 关于@ComponentScan
/ @Import/@Bean
/ @PropertySource
/ @ImportResource
.
4.1.4 @ComponentScan解析
从上面的源码中可以看出,解析@ComponentScan的核心代码是:
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
复制代码
我们来探究一波这个parse方法!
4.1.5 ComponentScanAnnotationParser#parse源码解析
从类名就可以看出, ComponentScanAnnotationParser
类是专门用于解析扫描并解析工程中@Componet注解的.其parse源码如下:
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
//创建一个scanner. 简单,继续往下
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
// 判断并设置scopedProxyMode. 简单,继续往下
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
// 设置资源路径. 简单,继续往下
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
// 设置includeFilters
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
// 设置excludeFilters. 简单,继续往下
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
// 设置lazyInit属性. 简单,继续往下
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
// 扫描的包路径. 简单,继续往下
Set<String> basePackages = new LinkedHashSet<>();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
// 开始扫描. 重要!!!
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
复制代码
4.1.6 ClassPathBeanDefinitionScanner#doScan源码解析
终于见到庐山真面目,doScan方法完成了包路径的扫描并吧符合条件的类生成BeanDefinition.
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 初始化一个bd set,用于盛放即将扫描并解析出来的bd!
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 遍历循环
for (String basePackage : basePackages) {
// 重要!!! 该方法便是去读取包路径下的资源,并解析出该包下所有符合条件的类生成bd.
// 本质上还是通过流的方式读取class文件然后对class对象进行解析并生成bd的.
// 看似高深莫测,实则 大道至简!
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 对当前包下的bd进行遍历加工,然后注册到BeanFactory中去!
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
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;
}
复制代码
4.2 postProcessBeanFactory源码解析
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
// 判断factoryId是否改变,如果改变,重新走一遍~~~
if (!this.registriesPostProcessed.contains(factoryId)) {
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
// 使用Cglib动态代理来增强配置类. 重要!!!
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
复制代码
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
// 找到所有配置类
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> resolve bean class at this point...
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
try {
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
// 判断是否是"完全"配置类,即@Configuration的配置类
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
// 没有"full"配置类,则直接返回
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
// 对"full"配置类进行增强,改变它的beanClass.
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);
}
}
}
复制代码
为什么要对"full"配置类进行增强?
继续跟踪源码,可以发现其对应的方法拦截器为: BeanMethodInterceptor
和BeanFactoryAwareMethodInterceptor
. 这两个方法拦截器主要是针对于@Bean
方法的调用行为处理和FactoryBean#getOjbect
行为的处理.具体为啥这样弄,我实在肝不动了~~我觉得这篇文章剖析的很好!
动态代理是非常重要的基础性知识.必须掌握 !!!
五. 总结
本篇文章对ConfigurationClassPostProcessor
类进行了较为详细的源码跟踪和解读. 它对于整个Spring框架可谓重中之重.
解析该后置处理之前,需要先熟悉整个Spring容器的启动过程,才能知道它的执行触发机制; 需要掌握@Configuration的基本概念和应用;需要对动态代理以及后置处理器有基本的概念. 这样在剖析源码时才能游刃有余.
通过本篇文章,知道了Spring是如何扫描项目中的类并变成BeanDefinition的.同时初步窥探了Spring当中的动态代理技术的应用.
作者:浪漫先生