Spring版本:
<version>5.2.1.RELEASE</version>
文章目录
上一篇:24-Spring源码解析之AOP(3)——解析@Aspect获取增强器
上一篇我们讲完了解析@Aspect
注解并获取增强器的时机和如何获取增强器。在获取增强器后,就是开始对创建的Bean
进行分析看其是否需要创建对应的AOP
代理。
那么本篇文章就开始讲解切面类(LogAspects
)和被切面类切入的类(MathCalculator
)在创建Bean
的时候AnnotationAwareAspectJAutoProxyCreator
所作的事情。本篇文章所用例子在文章22-Spring源码解析之AOP(1)——@EnableAspectJAutoProxy注解原理中。
首先我们需要意识到一点:实现AOP
功能是AnnotationAwareAspectJAutoProxyCreator
实现的,它是通过拦截每个Bean
的创建过程,然后对需要增强的Bean
进行代理。那么我们就需要弄清楚以下两个事情:
-
AnnotationAwareAspectJAutoProxyCreator
在创建Bean
的哪个地方进行拦截 -
AnnotationAwareAspectJAutoProxyCreator
拦截之后所作的工作有哪些
接下来我们就带着以上两个问题开始阅读本篇文章。
一、Bean
的创建过程
文章:23-Spring源码解析之AOP(2)——AnnotationAwareAspectJAutoProxyCreator类源码中我们分析过AnnotationAwareAspectJAutoProxyCreator
类的结构,忘记了不要紧,我把结论贴一下:
AnnotationAwareAspectJAutoProxyCreator
是一个BeanPostProcessor
。AnnotationAwareAspectJAutoProxyCreator
也是一个Ordered
。AnnotationAwareAspectJAutoProxyCreator
还是BeanFactoryAware
实现类
更具体地,AnnotationAwareAspectJAutoProxyCreator
是一个InstantiationAwareBeanPostProcessor
。
为了更清晰的了解 AnnotationAwareAspectJAutoProxyCreator
在创建Bean
的哪个地方进行拦截,我们还需要知道Spring
在Bean
在创建流程中的哪些地方留给了BeanPostProcessor
。下面我把Bean
的创建流程总结一下:
从上幅图片可以看出,在Bean
的创建过程中,有6个地方进行了BeanPostProcessor
的扩展(红色箭头区域)。(对Bean
创建感兴趣的同学可以翻看文章:16-Spring源码解析之Bean的生命周期(1)——doGetBean)。
但是我们知道:AnnotationAwareAspectJAutoProxyCreator
是一个InstantiationAwareBeanPostProcessor
,所以这6个扩展的地方并不都需要关注,只需要重点关注上图片中黄色箭头所指的5个区域即可。
还记得上篇文章中,解析@Aspect
获取增强器的过程是在上述图片中哪个区域吗?是在黄色箭头(1)区域。
接下来我们就开始讲解切面类(LogAspects
)和被切面类切入的类(MathCalculator
)在创建Bean
的时候图一中5个黄色区域所作的事情。
二、创建切面类LogAspects
2.1 箭头(1) resolveBeforeInstantiation
因为在这里会通过for
循环执行所有InstantiationAwareBeanPostProcessor
类型的的PostProcessor
的postProcessBeforeInstantiation
方法,这里只关注AnnotationAwareAspectJAutoProxyCreator
这个类型的InstantiationAwareBeanPostProcessor
。
进入postProcessBeforeInstantiation
方法
只执行了isInfrastructureClass
就直接进入下面的方法体,为什么没有执行shouldSkip
方法呢?因为,这里isInfrastructureClass
直接返回true
就不需要执行shouldSkip
方法就可以直接进入方法体了。
在方法体中,将logAspects
放到advisedBeans
中。我们现在可以看看advisedBeans
中的值。
执行完就返回了null
。
至此,resolveBeforeInstantiation
方法关于AOP
的功能实现就分析完了,resolveBeforeInstantiation
关于AOP
就做了一个事情:
- 将
logAspects
放到advisedBeans
中
2.2 箭头(2) populateBean
下面截取populate
方法在图一中箭头2的区域。
关注上图中if
语句,调用InstantiationAwareBeanPostProcessor
类的postProcessAfterInstantiation
方法。这里的InstantiationAwareBeanPostProcessor
类对应的是AnnotationAwareAspectJAutoProxyCreator
。我们看一下AnnotationAwareAspectJAutoProxyCreator
类的postProcessAfterInstantiation
方法实现。
AnnotationAwareAspectJAutoProxyCreator
类没有实现该方法,但是其父类AbstractAutoProxyCreator
实现了postProcessAfterInstantiation
方法。
从上图可以看出,该方法会永远返回true。所以在populateBean
方法的箭头(2) 区域的if
语句为false
,不会执行if
语句体中的语句。所以会继续执行属性赋值。
2.3 箭头(3) populateBean
下面截取populate
方法在图一中箭头3的区域。
我们进入AnnotationAwareAspectJAutoProxyCreator
类的postProcessProperties
方法实现。
从上图可以看出,AnnotationAwareAspectJAutoProxyCreator
类的父类没有对该方法作特殊的处理,只是直接返回了pvs
的值。
2.4 箭头(4) initializeBean
下面截取initializeBean
方法在图一中箭头4的区域。
从上图可以看出,在这里执行BeanPostProcessor
的时候,没有判断BeanPostProcessor
的具体类型,所以任何类型的BeanPostProcessor
都会被执行。
从上图可以看出,AnnotationAwareAspectJAutoProxyCreator
类的父类没有对该方法作特殊的处理,只是直接返回了bean
的值。
2.5 箭头(5) initializeBean
下面截取initializeBean
方法在图一中箭头5的区域。
从上图可以看出,在这里执行BeanPostProcessor
的时候,没有判断BeanPostProcessor
的具体类型,所以任何类型的BeanPostProcessor
都会被执行。我们关注当BeanPostProcessor
为AnnotationAwareAspectJAutoProxyCreator
时调用postProcessAfterInitialization
的情况。
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 根据给定的bean的class和name构建出一个key,格式 beanClassName_beanName
// 但是这里因为不是FactoryBean,所以返回的只是beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// ------------------------------------------核 心--------------------------------------------------
// 如果它适合被代理,则需要封装这个bean
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
if (StringUtils.hasLength(beanName)) {
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
}
else {
return beanClass;
}
}
我们进入wrapIfNecessary
方法
我们在【2.1 箭头(1) resolveBeforeInstantiation
】节将logAspects
放到advisedBeans
中,因此现在advisedBeans
中已经有logAspects
的值了,所以现在可以根据logAspects
键获取他的值,但是这里的值为false
,因此在上图中会直接返回bean
而不做任何处理。
这里如果不返回,会创建AOP
的代理对象!但是我们知道LogAspects
是切面类,而不是需要被织入增强器的类。
至此,我们完成了切面类LogAspects
对应的Bean
的创建。从上面分析可以知道,在创建切面类LogAspects
的过程中,与AOP
功能有关系的操作只有一个:即在resolveBeforeInstantiation
方法中将logAspects
放到advisedBeans
中。
即图一中只有上面红色箭头区域做的操作与AOP
功能有关。
接下来我们就开始讲解被切面类切入的类(MathCalculator
)在创建Bean
的时候图一中5个黄色区域所作的事情。
三、切面类切入的类(MathCalculator
)
3.1 箭头(1) resolveBeforeInstantiation
因为在这里会通过for
循环执行所有InstantiationAwareBeanPostProcessor
类型的的PostProcessor
的postProcessBeforeInstantiation
方法,这里只关注AnnotationAwareAspectJAutoProxyCreator
这个类型的InstantiationAwareBeanPostProcessor
。
进入postProcessBeforeInstantiation
方法。
当前advisedBeans
中的值只有两个:
mainConfig_AOP
->false
- 创建
mainConfig_AOP
的Bean
的时候放入advisedBeans
- 创建
logAspects
->false
- 创建
logAspects
的Bean
的时候放入advisedBeans
- 创建
注意在创建MathCalculator
时候的postProcessBeforeInstantiation
方法的执行过程与在创建LogAspects
时候的postProcessBeforeInstantiation
方法的执行过程不同。
在创建LogAspects
的时候isInfrastructureClass
方法返回值为true
,因此不会执行shouldSkip
方法直接返回null
。在创建MathCalculator
的时候isInfrastructureClass
方法返回值为false
,因此会执行shouldSkip
方法。
在MainConfig_AOP
类对应的Bean
创建的时候也进入了shouldSkip
方法,那个时候进入shouldSkip
方法的目的是:解析@Aspect
注解,将注解标注的类的增强器解析出来。
我们进入shouldSkip
方法。
我们进入findCandidateAdvisors
方法
我们继续进入:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
方法
首先从BeanFactoryAspectJAdvisorsBuilder
类的aspectBeanNames
属性中获取aspectBeanNames
,这个aspectBeanNames
值是在解析@Aspect
注解的时候放入的。忘记了?没关系,我在贴一次:
还是这个buildAspectJAdvisors
方法,只是在if (aspectNames == null)
条件成立的时候放入的。
但是当前aspectNames
中的值不为空,它的值为:被注解@Aspets
标注的类logAspects
对应的beanName
。因此不会再进入if (aspectNames == null)
,而是进入后面的语句。因为被注解@Aspets
标注的类可能不止一个,因此我们需要通过for
循环遍历每一个被注解@Aspets
标注的类。然后根据beanName
从advisorsCache
中获取这个Bean
的所有增强器。最后将获取到的advisors
返回。
返回到我们的shouldSkip
方法中,即图二。
在执行完findCandidateAdvisors
方法,返回的值放到candidateAdvisors
中。我们遍历获取到的candidateAdvisors
。当前candidateAdvisors
中有4个增强器。
但是这些Advisor
都不属于AspectJPointcutAdvisor
类型的,因此shouldSkip
方法返回false
。我们回调调用shouldSkip
的方法postProcessBeforeInstantiation
。
这里targetSource
方法返回null
,所以postProcessBeforeInstantiation
方法会返回null
。
至此,我们将图一的黄色箭头(1) resolveBeforeInstantiation
分析完。而黄色箭头(1) resolveBeforeInstantiation
处关于AOP
功能似乎什么都没有做。也没有将mathCalculator
放到advisedBeans
中
3.2 箭头(2) populateBean
下面截取populate
方法在图一中箭头2的区域。
关注上图中if
语句,调用InstantiationAwareBeanPostProcessor
类的postProcessAfterInstantiation
方法。这里的InstantiationAwareBeanPostProcessor
类对应的是AnnotationAwareAspectJAutoProxyCreator
。我们看一下AnnotationAwareAspectJAutoProxyCreator
类的postProcessAfterInstantiation
方法实现。
AnnotationAwareAspectJAutoProxyCreator
类没有实现该方法,但是其父类AbstractAutoProxyCreator
实现了postProcessAfterInstantiation
方法。
从上图可以看出,该方法会永远返回true。所以在populateBean
方法的箭头(2) 区域的if
语句为false
,不会执行if
语句体中的语句。所以会继续执行属性赋值。
3.3 箭头(3) populateBean
下面截取populate
方法在图一中箭头3的区域。
我们进入AnnotationAwareAspectJAutoProxyCreator
类的postProcessProperties
方法实现。
从上图可以看出,AnnotationAwareAspectJAutoProxyCreator
类的父类没有对该方法作特殊的处理,只是直接返回了pvs
的值。
3.4 箭头(4) initializeBean
下面截取initializeBean
方法在图一中箭头4的区域。
从上图可以看出,在这里执行BeanPostProcessor
的时候,没有判断BeanPostProcessor
的具体类型,所以任何类型的BeanPostProcessor
都会被执行。
从上图可以看出,AnnotationAwareAspectJAutoProxyCreator
类的父类没有对该方法作特殊的处理,只是直接返回了bean
的值。
3.5 箭头(5) initializeBean
下面截取initializeBean
方法在图一中箭头5的区域。
我们只关心与AOP
功能有关的BeanPostProcessor
。因此,我们遍历到BeanPostProcessor
为AnnotationAwareAspectJAutoProxyCreator
。我们进入AnnotationAwareAspectJAutoProxyCreator
类的postProcessAfterInitialization
方法中。
我们进入wrapIfNecessary
方法。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 已经处理过,则直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 无需增强
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 给定的Bean类是否代表一个基础设施类,基础设施类不应被代理,或者配置了指定bean不需要自动代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// ---------------------------------------【功能一】--3.5.1 详细介绍-------------------------------------
// ----------------------------------核心方法 ----------------------------------
// 获取增强器并判断获取到的增强器是否适合当前的Bean
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果获取到了增强器则需要针对增强器进行代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
// ---------------------------------------【功能二】--3.5.2 详细介绍-------------------------------------
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
当前advisedBeans
中只有2个值。
3.5.1 getAdvicesAndAdvisorsForBean
获取增强器
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取到候选的所有增强器
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
我们进入findEligibleAdvisors
方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// ----------------------【功能一】---与3.1 箭头(1) `resolveBeforeInstantiation`一样--------------------
// 获取所有的增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// ---------------------------------------【功能二】----下面详细分析-----------------------------------
// 寻找所有增强器中适用于当前Bean的增强器并应用
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
因为findEligibleAdvisors
方法中调用的findCandidateAdvisors
方法我们已经分析完了,所以这里就再次赘述了。直接给出执行完findCandidateAdvisors
的结果。
我们带着candidateAdvisors
来进入 findEligibleAdvisors
方法的【功能二】 findAdvisorsThatCanApply
方法
3.5.1.1 findEligibleAdvisors
方法的【功能二】 findAdvisorsThatCanApply
该方法的功能:寻找匹配的增强器
前面的函数中已经完成了所有增强器的解析,但是对于所有增强器来讲,并不一定都适用于当前的Bean
,还要挑取出适合的增强器,也就是满足我们配置的通配符的增强器。具体实现在findAdvisorsThatCanApply
方法中。
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 过滤已经得到的advisors
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
进入findAdvisorsThatCanApply
方法
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 首先处理引介增强,本例子中没有引介增强,这里不具体分析
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
// 引介增强已经处理
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// ---------------------------------------核心方法-------------------------------------
// 对于普通的Bean的处理
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
findAdvisorsThatCanApply
方法的主要功能是寻找所有增强器中使用与当前bean
的增强器。引介增强与普通的增强是处理不一样的,所以分开处理。而对于真正的匹配在canApply
实现。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
// 当前例子的advisor是属于PointcutAdvisor类型
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
我们继续进入canApply
方法
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
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 introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
// 获取当前类的所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 找到当前类中的方法与增强器方法一样的方法,如果找到了就返回true
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
因为当前类MathCalculator
的div
方法是被现有的增强器增强的方法,所以返回true
。
返回true
就说明它找到匹配的增强器了,说明在 3.5.1 getAdvicesAndAdvisorsForBean
获取增强器节中返回需要代理。我们一直返回到wrapIfNecessary
方法中。
我们看到执行完Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
方法后,它做了两个事情:
this.advisedBeans.put(mathCalculator, Boolean.TRUE);
Object proxy = createProxy(....)
创建代理
3.5.2 createProxy
创建代理
在获取了所有对应Bean
的增强器之后,便可以进行代理的创建了。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
// ---------------------------------------【功能一】---------------------------------------
// 提取当前类中的相关属性
proxyFactory.copyFrom(this);
// ---------------------------------------【功能二】---------------------------------------
// 决定对于给定的Bean是否应该使用 targetClass而不是它的接口代理
// 检查proxyTargetClass设置以及preserveTargetClass属性
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// ---------------------------------------【功能三】--核心--3.5.2.1 详细分析--------------------------------
// 使用Advisor封装拦截器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 加入增强器
proxyFactory.addAdvisors(advisors);
// ---------------------------------------【功能四】---------------------------------------
// 设置要代理的类
proxyFactory.setTargetSource(targetSource);
// ---------------------------------------【功能五】---------------------------------------
// 定制代理
customizeProxyFactory(proxyFactory);
// 用来控制代理工厂被配置之后,是否还允许修改通知。
// 缺省值为false(即在代理被配置之后,不允许修改代理的配置)
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// ---------------------------------------【功能六】--核心--3.5.2.2 详细分析--------------------------------
return proxyFactory.getProxy(getProxyClassLoader());
}
对于代理类的创建以及处理,Spring
委托给了ProxyFactory
去处理,而在此函数中主要是对ProxyFactory
的初始化操作,进而为真正的创建代理做准备,这些初始化操作包括如下内容:
- 【功能一】获取当前类中的属性
- 【功能二】添加代理接口
- 【功能三】封装
Advisor
并加入到ProxyFactory
- 【功能四】设置要代理的类
- 【功能五】在
Spring
中还为子类提供了定制的函数customizeProxyFactory
,子类可以在此函数中进行对ProxyFactory
的进一步封装 - 【功能六】进行获取代理操作
其中【功能三】封装Advisor
并加入到ProxyFactory
是一个非常重要的功能。我们接下来看一下Spring
是如何通过buildAdvisors
来封装拦截器的。
3.5.2.1 buildAdvisors
方法
我们先来看一下buildAdvisors
方法中传入的参数的值
我们进入buildAdvisors
方法
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
// 解析注册的所有InterceptorName
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
// 加入拦截器
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
// 此处处理Log日志省略
...
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// ---------------------------------------核 心------------------------------------------------
// 拦截器进行封装转化为Advisor
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
我们进入this.advisorAdapterRegistry.wrap
看它是如何封装的
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 如果要封装的对象本身就是Advisor类型的那就直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 因为这个封装方法只对Advisor和Advice两个类型的数据有效,因此如果不是这两个类型就不能封装
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
// 如果是MethodInterceptor类型,就使用DefaultPointcutAdvisor来封装
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
// 如果存在Advisor的适配器那么也同样需要进行封装
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
而本例子中,传入wrap
方法的参数就是Advisor
类型的(3.5.1
节讲过),因此if (adviceObject instanceof Advisor)
我为true
直接返回。
我们把所有的增强器都封装起来,并将他放到ProxyFactory
后,即完成了createProxy
方法的【功能三】。我们回到createProxy
方法。
3.5.2.2 proxyFactory.getProxy(getProxyClassLoader())
方法
createProxy
的最后一个功能就是代理的创建与获取。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
...
// 前面的功能省略
return proxyFactory.getProxy(getProxyClassLoader());
}
我们进入proxyFactory
的getProxy
方法
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
具体是如何创建代理并获取代理的我们下一篇文章详细讲解。
四、总结
整篇文章从图一开始讲起,分析切面类LogAspect
和被切面类切入的类(MathCalculator
)在创建Bean
的时候AnnotationAwareAspectJAutoProxyCreator
所作的事情。相信从上面的分析中也可以看出,由于AnnotationAwareAspectJAutoProxyCreator
是一个BeanPostProcessor
,因此任何Bean
在创建的时候都会被拦截并且做一些事情。只是对于不同类型的Bean
所做的事情不一样而已。我们可以把Bean
分成两类来看:
-
普通
Bean
-> 非被切面类切入的类- 只是在
resolveBeforeInstantiation
时将该类对于的BeanName
作为键放到了advisors
中,值为false
- 只是在
-
被切面类切入的类
- 在
resolveBeforeInstantiation
时什么都不做 - 在
initializeBean
->applyBeanPostProcessorsAfterInitialization
时getAdvicesAndAdvisorsForBean
获取增强器并判断当前Bean
是否与增强器相匹配createProxy
创建代理
- 在
至此,所有需要创建代理对象的信息已经解析完了,下一篇文章我们开始讲解以下两个问题:
Spring
是如何通过createAopProxy();
方法创建代理Spring
是如何通过getProxy(classLoader)
方法获取代理