Commit 02d69ecd by SunWei峰

吃透AOP

parent 59c81472
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.6.20" />
</component>
</project>
\ No newline at end of file
......@@ -5,9 +5,4 @@
<file type="web" url="file://$PROJECT_DIR$/spring-framework-main" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="17" project-jdk-type="JavaSDK" />
<component name="SwUserDefinedSpecifications">
<option name="specTypeByUrl">
<map />
</option>
</component>
</project>
\ No newline at end of file
......@@ -89,9 +89,11 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 直接获取 容器中的 Advisor 类型的Bean
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 主要获取我们通过注解方式动态注册的 Advisors,比如根据不同表达式获取到的不同切点
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
......
......@@ -84,13 +84,13 @@ public class BeanFactoryAspectJAdvisorsBuilder {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
// 如果为空表示尚未缓存,进行缓存解析。这里用了DLC 方式来进行判断
// 如果为空表示尚未缓存,进行缓存解析。这里用了 DLC 方式来进行判断
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 1. 获取所有的beanName。从容器中获取所有的BeanName
// 1. 获取所有的 beanName。从容器中获取所有的BeanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 遍历beanName, 找出对应的增强方法
......@@ -105,7 +105,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
if (beanType == null) {
continue;
}
// 2. 如果bean 被 @AspectJ 注解修饰 且不是 Ajc 编译, 则进一步处理
// 2. 如果 bean 被 @AspectJ 注解修饰 且不是 Ajc 编译, 则进一步处理
if (this.advisorFactory.isAspect(beanType)) {
// 添加到缓存中
aspectNames.add(beanName);
......@@ -114,9 +114,11 @@ public class BeanFactoryAspectJAdvisorsBuilder {
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 3. 解析标记AspectJ注解中的增强方法,也就是被 @Before、@Around 等注解修饰的方法,并将其封装成 Advisor
// 3. 解析标记 AspectJ 注解中的增强方法,也就是被 @Before、@Around 等注解修饰的方法,并将其封装成 Advisor
// 每个方法解析成一个 Advisors
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 完成后加入缓存(单例)
this.advisorsCache.put(beanName, classAdvisors);
}
else {
......@@ -151,6 +153,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
// 4. 将所有的增强方法保存到缓存中。
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
// 一个类可能有多个 Advisor
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
......
......@@ -146,7 +146,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
// discovered via reflection in order to support reliable advice ordering across JVM launches.
// Specifically, a value of 0 aligns with the default value used in
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
// 将方法封装成 Advisor 。如果找不到@PointCut 的信息,则会返回 null。
// 将方法封装成 Advisor 。如果找不到 @PointCut 的信息,则会返回 null。
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
......
......@@ -98,13 +98,19 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// 寻找所有候选代理增强点。
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 从前面的代码分析可以看出,如果是 Aop 的动态封装都是基于 InstantiationModelAwarePointcutAdvisorImpl
// 也就是 InstantiationModelAwarePointcutAdvisor,自然是继承 PointcutAdvisor
// (IntroductionAdvisor 只能用于类级别的拦截,Introduction 型的 Advice;pointcutAdvisor 则都可以)
// 如果代理类基于 AspectJPointcutAdvisor && aspectName==beanName,即当前初始化的类是ApspectJ类本身。则返回true,跳过代理
if (advisor instanceof AspectJPointcutAdvisor pointcutAdvisor &&
pointcutAdvisor.getAspectName().equals(beanName)) {
return true;
}
}
// 父类shouldSkip 判断了文件是否是 .ORIGINAL 后缀,是则跳过。
return super.shouldSkip(beanClass, beanName);
}
......
......@@ -58,6 +58,7 @@ public abstract class AopConfigUtils {
static {
// Set up the escalation list...
// 下表越大,优先级越高
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
......@@ -127,6 +128,7 @@ public abstract class AopConfigUtils {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 优先级大的为主
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
......
......@@ -60,6 +60,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
// 我们这里的Advisor 都是 PointcutAdvisor 所以这里只分析该内容
if (advisor instanceof PointcutAdvisor pointcutAdvisor) {
// Add it conditionally.
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
......@@ -74,12 +75,15 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
else {
match = mm.matches(method, actualClass);
}
// 如果代理规则与当前类匹配
if (match) {
// 进行转化注册
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
// 封装成 InterceptorAndDynamicMethodMatcher
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
......
......@@ -108,7 +108,9 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
// 分析出要代理的接口
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 设置代理属性
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
......@@ -188,7 +190,9 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
}
Object retVal;
// 是否暴露代理对象。有时候目标对象内部的自我调用将无法实施切面中的增强,则需要通过此属性暴露
// 如果exposeProxy属性值为true,则将代理对象暴露到ThreadLocal中
// exposeProxy是通过注解@EnableAspectJAutoProxy(exposeProxy = true)进行指定的,如果配置为true,
// 则可以使用AopContext.currentProxy()获取到代理对象. 在Spring事务方法自调用的时候经常使用到.
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
......@@ -218,7 +222,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
else {
// We need to create a method invocation...
// 否则构建一个新的 方法调用对象 ReflectiveMethodInvocation
// 以便于使用proceed 方法进行链接表用拦截器
// 以便于使用 proceed 方法进行链接表用拦截器
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
......
......@@ -159,7 +159,7 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 执行完所有增强后执行切点方法
// 执行完所有增强后执行切点方法,利用索引达到链式访问
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
......
......@@ -82,9 +82,12 @@ public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Se
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
// 如果 Advice 就是MethodInterceptor 类型,则直接保存
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 否则寻找合适的适配器进行转换。
// 这里的适配器有三个,分别是`AfterReturningAdviceAdapter`、`MethodBeforeAdviceAdapter`、`ThrowsAdviceAdapter`
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
......
......@@ -93,9 +93,10 @@ public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyC
* @see #extendAdvisors
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取所有的增强
// 获取所有的增强(缓存中只有 name 字符串,需要 get,若没有初始化要先初始化)
// 另外子类会解析表达式等切面
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 寻找增强中适用于bean的增强并应用
// 寻找增强中适用于 bean 的增强并应用
// 搜索给定的候选增强以查找可以应用于指定 bean 的所有增强。
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 在链表首部,添加增强链增强
......
......@@ -250,9 +250,11 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 已经代理过
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 基础类或代理本身则跳过
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
......@@ -262,6 +264,9 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
// 获取封装当前 bean 的 TargetSource 对象,如果不存在,则直接退出当前方法,否则从 TargetSource
// 中获取当前 bean 对象,并且判断是否需要将切面逻辑应用在当前 bean 上。
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
......@@ -339,7 +344,9 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
return bean;
}
// 给定的bean是否代表一个基础设施类,基础设施类不应代理,或者配置了指定的bean不需要自动代理
// 不能代理基础类或者代理本身
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 不代理也要记录下来
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
......@@ -454,7 +461,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
// 获取当前类中属性
proxyFactory.copyFrom(this);
// 决定对于给定的 bean 是否应该使用 targetClass 属性 而不是他的代理接口
// 决定对于给定的 bean 是否应该使用 targetClass 属性而不是他的代理接口
// 检查 ProxyTargetClass 设置以及 preserveTargetClass
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
......@@ -477,6 +484,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
}
}
// 不仅之前解析的,也有可能用户注入了拦截器,都要添加进去
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 加入增强器
proxyFactory.addAdvisors(advisors);
......@@ -580,6 +588,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
BeanFactory bf = this.beanFactory;
ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
List<Advisor> advisors = new ArrayList<>();
// 将 interceptorNames 获取到的拦截器保存起来,并返回。用户会通过 set 方法添加
for (String beanName : this.interceptorNames) {
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
......
......@@ -79,7 +79,7 @@ public class BeanFactoryAdvisorRetrievalHelper {
return new ArrayList<>();
}
// 遍历所有的beanName找到对应的增强方法
// 遍历所有的 beanName 找到对应的增强方法
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
// 合法情况
......
......@@ -227,12 +227,14 @@ public abstract class AopUtils {
return false;
}
// 获取切点的方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
// 这里 introductionAwareMethodMatcher 的实现是 AspectJExpressionPointcut
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
......@@ -246,8 +248,11 @@ public abstract class AopUtils {
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
// 获取当前bean的所有方法
for (Method method : methods) {
// 在这里判断方法是否匹配
if (introductionAwareMethodMatcher != null ?
// 这里调用 AspectJExpressionPointcut#matches
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
......
......@@ -321,7 +321,7 @@ class ConstructorResolver {
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
// 如果 已经找到候选构造函数,且当前这个构造函数也有相同的类似度则保存到 ambiguousConstructors 中。后面用于抛出异常
// 如果已经找到候选构造函数,且当前这个构造函数也有相同的类似度则保存到 ambiguousConstructors 中。后面用于抛出异常
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
......
......@@ -42,14 +42,18 @@ class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册 AspectJ 注释自动代理创建器。这里注册的自动代理创建器 Aop 实现的核心。
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 获取 @EnableAspectJAutoProxy 注解
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
// 解析 proxyTargetClass 属性(是否使用cglib代理)
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 解析 exposeProxy 属性(是否暴露代理对象)
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
......
......@@ -153,6 +153,7 @@ class ConfigurationClassBeanDefinitionReader {
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// AOP 自动代理创建器的注册就在这一步
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
......@@ -160,6 +161,7 @@ class ConfigurationClassBeanDefinitionReader {
* Register the {@link Configuration} class itself as a bean definition.
*/
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
// 就是将引入的配置类注册为 BeanDefinition
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
......@@ -169,7 +171,9 @@ class ConfigurationClassBeanDefinitionReader {
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
// 创建代理,根据 scopeMetadata 的代理模式。默认不创建代理。
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册了 BeanBeanDefinition
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
......
......@@ -246,7 +246,7 @@ class ConfigurationClassParser {
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);
......@@ -283,10 +283,12 @@ class ConfigurationClassParser {
}
// Process any @PropertySource annotations
// 去重后遍历 PropertySource 注解所指向的属性。注意:两个注解@PropertySources 和 @PropertySource。
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
// 解析
processPropertySource(propertySource);
}
else {
......@@ -296,12 +298,15 @@ class ConfigurationClassParser {
}
// Process any @ComponentScan annotations
// 将 @ComponentScans 中的多个 @ComponentScan 解析出来封装成一个一个AnnotationAttributes对象
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
// 如果当前配置类被 @componentScans 或 @componentScan 注解修饰 && 不应跳过
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
// 直接执行扫描,根据指定路径扫描出来bean。
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
......@@ -310,6 +315,7 @@ class ConfigurationClassParser {
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// 检测如果是配置类,则递归调用 parse 解析。
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
......@@ -318,9 +324,11 @@ class ConfigurationClassParser {
}
// Process any @Import annotations
// @Import、@ImportSelector、@ImportBeanDefinitionRegistrar都在这儿
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
// @ImportResource 直接保存到 configClass 中。
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
......@@ -333,12 +341,14 @@ class ConfigurationClassParser {
}
// Process individual @Bean methods
// 直接保存到 configClass 的中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 检测配置类实现的接口中的默认方法是否被@Bean修饰
processInterfaces(configClass, sourceClass);
// Process superclass, if any
......@@ -375,7 +385,7 @@ class ConfigurationClassParser {
}
}
OrderComparator.sort(candidates);
// dfs 解析内部类
// dfs 解析内部类(开始前要注意防止循环导入)
for (SourceClass candidate : candidates) {
if (this.importStack.contains(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
......@@ -472,8 +482,10 @@ class ConfigurationClassParser {
for (String location : locations) {
try {
// 解决占位符,获取真正路径
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
Resource resource = this.resourceLoader.getResource(resolvedLocation);
// 保存
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
......@@ -494,6 +506,7 @@ class ConfigurationClassParser {
String name = propertySource.getName();
MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
// 解决重复问题
if (this.propertySourceNames.contains(name)) {
// We've already added a version, we need to extend it
PropertySource<?> existing = propertySources.get(name);
......@@ -578,9 +591,11 @@ class ConfigurationClassParser {
else {
this.importStack.push(configClass);
try {
// dfs
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
// 判断是否是ImportSelector类型。ImportSelector 则需要调用selectImports 方法来获取需要注入的类。
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
......@@ -594,9 +609,11 @@ class ConfigurationClassParser {
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 调用 selectImports 方法获取需要引入的类,并递归再次处理。
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
// 如果是 ImportBeanDefinitionRegistrar 类型,则委托它注册其他bean定义
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
......@@ -609,6 +626,7 @@ class ConfigurationClassParser {
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
// 否则递归处理需要引入的类。
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
......
......@@ -139,7 +139,6 @@ abstract class ConfigurationClassUtils {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 如果被 @Configuration 修饰 && isConfigurationCandidate(metadata) = true
// 关于 isConfigurationCandidate(metadata) 的解析在下面
else if (config != null || isConfigurationCandidate(metadata)) {
// 设置 CONFIGURATION_CLASS_ATTRIBUTE 为 lite
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment