Spring-AOP-原理

如果我们自己实现一个AOP?

什么时候生成代理对象呢?

肯定是普通的 bean 在初始化阶段,被 BeanPostProcessor 影响后,在 postProcessAfterInitialization 方法中生成代理对象吧!

解析切入点表达式的时机

在 AOP 核心后置处理器的初始化阶段,解析容器中的所有切面类中的切入点表达式。

通知织入的方式

底层实现是通过动态代理。动态代理分为jdk动态代理,Cglib动态代理。条件选择合适的动态代理进行通知织入。

总体思路就是:
1.通过后置处理器,拦截切面类,筛选出所有切入点表达式。
2.bean初始化的时候调用后置处理器,匹配bean是否符合切入点表达式。
3.对于符合的,找到对应方法,通过动态代理织入增强的逻辑,返回代理的对象。

AOP代理的底层核心后置处理器

这个要从我们配置的开启AOP的注解看起。—@EnableAspectJAutoProxy

@EnableAspectJAutoProxy

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;
}

可以发现,里面有个@Import注解,导入了一个AspectJAutoProxyRegistrar

AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    AspectJAutoProxyRegistrar() {
    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    //注册核心后置处理器的动作
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    //解析@EnableAspectJAutoProxy的属性并配置
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }

    }

可以发现这个类实现ImportBeanDefinitionRegistrar 接口。向IOC容器注入BeanDefinition:

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

在这里插入图片描述
可以发现,已经指定要注册的类型是:AnnotationAwareAspectJAutoProxyCreator
进入下面的注册方法:

 @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
            BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }

            return null;
        } else {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", -2147483648);
            beanDefinition.setRole(2);
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
            return beanDefinition;
        }
    }

AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator 它兼顾 AspectJ 风格的切面声明,以及 SpringFramework 原生的 AOP 编程
在这里插入图片描述

AnnotationAwareAspectJAutoProxyCreator实现的几个重要的接口:
1.BeanPostProcessor。通过调用 postProcessAfterInitialization生成代理对象。

2.InstantiationAwareBeanPostProcessor:连接bean的正常的doCreateBean创建流程。

3.SmartInstantiationAwareBeanPostProcessor:提前预测 bean 的类型、暴露 bean 的引用。

4.AopInfrastructureBean :实现了该接口的 bean 永远不会被代理(防止套娃)。

什么时候创建这个后置处理器:AnnotationAwareAspectJAutoProxyCreator

在Bean的实例化阶段,调用AbstractApplicationContext#refresh的registerBeanPostProcessors(beanFactory);方法。注册初始化BeanPostProcessor后置处理器。

由于AnnotationAwareAspectJAutoProxyCreator实现Ordered接口,它会提前与普通的BeanPostProcessor创建。
在这里插入图片描述

AnnotationAwareAspectJAutoProxyCreator什么时候起作用

当这个后置处理器被创建初始化后,所有的bean实例都应该被它干预。
bean的创建流程:
在这里插入图片描述

在doCreatBean中进行创建对象,属性赋值,组件注入,初始化的流程。
当初始化执行完毕,就该BeanPostProcessor 后置处理器的postProcessAfterIntialization 方法。

AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation

//AbstractAutoProxyCreator#postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);

    // 决定是否要提前增强当前bean
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        // 被增强过的bean不会再次被增强
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 基础类型的bean不会被提前增强、被跳过的bean不会被提前增强
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // 原型bean的额外处理:TargetSource
    // 此处的设计与自定义TargetSource相关,单实例bean必定返回null
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    return null;
}

isInfrastructureClass

基础类型的bean。

protected boolean isInfrastructureClass(Class<?> beanClass) {
    return (super.isInfrastructureClass(beanClass) ||
            (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}

protected boolean isInfrastructureClass(Class<?> beanClass) {
    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
            Pointcut.class.isAssignableFrom(beanClass) ||
            Advisor.class.isAssignableFrom(beanClass) ||
            AopInfrastructureBean.class.isAssignableFrom(beanClass);
    // logger ......
    return retVal;
}

其实就是切面,切入点,增强器等对象。这些作为底层的组成成员,不应该参与具体的增强器对象中。

shouldSkip

// AspectJAwareAdvisorAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 加载增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        // 逐个匹配,如果发现当前bean的名称与增强器的名称一致,则认为
        if (advisor instanceof AspectJPointcutAdvisor &&
                ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }
    return super.shouldSkip(beanClass, beanName);
}

// AbstractAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 检查beanName代表的是不是原始对象(以.ORIGINAL结尾)
    return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}

1.当前bean是不是有增强器名称一样的。
  一般情况,我们构造的 bean 根本就不可能带有 .ORIGINAL 的后缀,所以这个地方相当于判断当前创建的 bean 是否名称与增强器撞车。

2.当前bean是不是一个还没有经过任何代理的原始对象。
一个Advisor = 一个pointcut + 一个advice。
切面类(Aspect)中定义的通知方法,方法体 + 方法上的通知注解就可以看做是一个Advisor增强器。

3.AOP 的代理其实不是代理的目标对象本身,而是目标对象包装后的 TargetSource 对象。

AOP切面类的收集findCandidateAdvisors

findCandidateAdvisors方法就是解析切面类,构造增强器的过程。

protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    // 根据父类的规则添加所有找到的Spring原生的增强器
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    // 解析BeanFactory中所有的AspectJ切面,并构造增强器
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

核心步骤:
1.找到Spring框架原生的AOP增强器
2.解析切面类,并构造增强器

super.findCandidateAdvisors

private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;

protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

可以发现它通过BeanFactoryAdvisorRetrievalHelper的方法findAdvisorBeans来查找原生的AOP增强器。

进入findAdvisorBeans方法:

public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    // 确定增强器bean名称的列表(如果尚未缓存)
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the auto-proxy creator apply to them!
        // 不要在这里初始化FactoryBeans:
        // 我们需要保留所有未初始化的常规bean,以使自动代理创建者对其应用
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    // 如果当前IOC容器中没有任何增强器类型的bean,直接返回
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }
    // ......

就是将IOC容器中所有类型是Advisor的实现类都找出来。
BeanFactoryUtils 的 beanNamesForTypeIncludingAncestors 方法,底层是用的 getBeanNamesForType 方法去找 bean 的名称。

如果没有找到,直接返回。
如果找到有Advisor的实现类。进行初始化原生增强器

 List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                // logger ......
            }
            else {
                try {
                    //初始化原生的增强器
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                } // catch ......
            }
        }
    }
    return advisors;
}

aspectJAdvisorsBuilder.buildAspectJAdvisors

核心就是:将 Aspect 切面类,转换为一个一个的增强器

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;

    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                // 获取IOC容器中的所有bean
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
                    // We must be careful not to instantiate beans eagerly as in this case they
                    // would be cached by the Spring container but would not have been weaved.
                    // 我们必须小心,不要急于实例化bean,因为在这种情况下,IOC容器会缓存它们,但不会被织入增强器
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }
                    // ......

核心逻辑:
将IOC容器中所有的beanNames都取出来,获取每个bean的Class。
接下来进行Aspect类型的切面解析。

  // ......
  //isAspect方法判断beanType是否是@Aspect注解标注的类
    if (this.advisorFactory.isAspect(beanType)) {
        // 当前解析bean的所属类型是一个切面类
        aspectNames.add(beanName);
        AspectMetadata amd = new AspectMetadata(beanType, beanName);
        // 下面是单实例切面bean会走的流程
        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
            MetadataAwareAspectInstanceFactory factory =
                    new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
            // 解析生成增强器
            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
            if (this.beanFactory.isSingleton(beanName)) {
                this.advisorsCache.put(beanName, classAdvisors);
            }
            else {
                this.aspectFactoryCache.put(beanName, factory);
            }
            advisors.addAll(classAdvisors);
        }
        // ......

isAspect方法判断是否是@Aspect标注的类。

advisorFactroy.getAdvisors构造增强器。

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    // Aspect切面类的Class
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    // 再次校验一下切面类上是不是标注了@Aspect注解
    validate(aspectClass);

    // 此处利用Decorator装饰者模式,目的是保证Advisor增强器不会被多次实例化
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
            new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();
    // 逐个解析通知方法,并封装为增强器
    for (Method method : getAdvisorMethods(aspectClass)) {
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // If it's a per target aspect, emit the dummy instantiating aspect.
    // 通过在装饰者内部的开始加入SyntheticInstantiationAdvisor增强器,达到延迟初始化切面bean的目的
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

    // Find introduction fields.
    // 对@DeclareParent注解功能的支持(AspectJ的引介)
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    return advisors;
}

切面类中通知方法的收集getAdvisorMethods

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new ArrayList<>();
    ReflectionUtils.doWithMethods(aspectClass, method -> {
        // Exclude pointcuts
        if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
            methods.add(method);
        }
    }, ReflectionUtils.USER_DECLARED_METHODS);
    if (methods.size() > 1) {
        methods.sort(METHOD_COMPARATOR);
    }
    return methods;
}

核心逻辑:将切面类中,除了@Pointcut标注的通用切入点表达式外,其他的方法都提取出来。并按照Unicode编码排序。

创建增强器getAdvisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
        int declarationOrderInAspect, String aspectName) {
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    
    //解析通知注解上的切入点表达式
    AspectJExpressionPointcut expressionPointcut = getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    // 没有声明通知注解的方法也会被过滤
    if (expressionPointcut == null) {
        return null;
    }
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

创建增强器通过new InstantiationModelAwarePointcutAdvisorImpl。
构造函数出入一下几个参数:
1.expressionPointcut:切入点表达式
2.candidateAdviceMethod:通知方法本体
3.this:当前的ReflectiveAspectJAdvisorFactory
4.aspectInstanceFactory:装饰者 MetadataAwareAspectInstanceFactory

增强器的结构就是:一个切入点表达式 + 一个通知方法。

原型切面bean的处理

  // ......
                else {
                    // Per target or per this.
                    if (this.beanFactory.isSingleton(beanName)) {
                        throw new IllegalArgumentException("Bean with name '" + beanName +
                                "' is a singleton, but aspect instantiation model is not singleton");
                    }
                    MetadataAwareAspectInstanceFactory factory =
                            new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                    this.aspectFactoryCache.put(beanName, factory);
                    // 解析Aspect切面类,构造增强器
                    advisors.addAll(this.advisorFactory.getAdvisors(factory));
                }
            }
        }
        this.aspectBeanNames = aspectNames;
        return advisors;
    }
    // ......

它的核心解析动作依然是 advisorFactory.getAdvisors 方法,只是这里面不会再用到 advisorsCache 这个缓存区了,这也说明原型切面 bean 的解析是多次执行的。

增强器汇总

  if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    List<Advisor> advisors = new ArrayList<>();
    for (String aspectName : aspectNames) {
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        }
        else {
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    return advisors;
}

AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization

前面的拦截结束,在起作用就到了后面bean初始化之后调用postProcessAfterInitialization 方法。

//AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
       //如果是工厂bean,返回&+beanName,否则返回beanName。如果beanName为空,bean.getClass对象。
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 核心:构造代理
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

核心方法:wrapIfNecessary。如果有必要的话,给这个对象包装生成代理对象。

wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 判断决定是否是不会被增强的 bean
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // 如果上面的判断都没有成立,则决定是否需要进行代理对象的创建
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理对象的动作
       // 注意此处它创建了一个SingletonTargetSource,将bean包装起来了
        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;
}

核心步骤:
1.判断当前bean是否是不被增强的bean。
2.根据当前bean去匹配增强器。
3.如果增前期不为空,创建代理对象

getAdvicesAndAdvisorsForBean

根据当前bean去匹配增强器

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) {
    // 获取所有增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 筛选出可以切入当前bean的增强器
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 添加额外的增强器
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 增强器排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

取出所有的增强器,筛选出可以切入当前bean的增强器,添加额外的增强器,进行排序。

findCandidateAdvisors

protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

将Spring框架原生的增强器和AspectJ形式封装的增强器都拿出来。

findAdvisorsThatCanApply

protected List<Advisor> findAdvisorsThatCanApply(
        List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    } finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

通过AopUtils的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;
        }
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

前面是针对引介通知的增强器作筛选,后面是普通的方法通知封装的增强器。
一下是普通的方法通知匹配:

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    // 对于引介增强器,它会直接强转,使用类级别的过滤器去匹配
    if (advisor instanceof IntroductionAdvisor) {
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    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.
        // SpringFramework也不知道咋搞了,于是就直接让它可以匹配
        return true;
    }
}
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) {
        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) {
        // 逐个判断每个方法是否能被当前切入点表达式切入,切入则立即返回true
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        for (Method method : methods) {
            if (introductionAwareMethodMatcher != null ?
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}

最终eligibleAdvisors集合中存放的就是匹配到的增强器。

extendAdvisors

dug会发现,过了这个方法后eligibleAdvisors集合中会多了一个增强器。
在这里插入图片描述

protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}

// AspectJProxyUtils
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    // Don't add advisors to an empty list; may indicate that proxying is just not required
    if (!advisors.isEmpty()) {
        boolean foundAspectJAdvice = false;
        for (Advisor advisor : advisors) {
            // Be careful not to get the Advice without a guard, as this might eagerly
            // instantiate a non-singleton AspectJ aspect...
            if (isAspectJAdvice(advisor)) {
                foundAspectJAdvice = true;
                break;
            }
        }
        // 发现有AspectJ包装的增强器,则添加一个ExposeInvocationInterceptor
        if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
            advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
            return true;
        }
    }
    return false;
}

判断当前可用的增强器中有没有 AspectJ 类型的,如果有的话,那就在整个增强器的列表的最前面,添加一个 ExposeInvocationInterceptor.ADVISOR 。

ADVISOR如下:

 
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();

public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
    @Override
    public String toString() {
        return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
    }
};

ExposeInvocationInterceptor如下:

private static final ThreadLocal<MethodInvocation> invocation =
			new NamedThreadLocal<>("Current AOP method invocation");

public Object invoke(MethodInvocation mi) throws Throwable {
    MethodInvocation oldInvocation = invocation.get();
    invocation.set(mi);
    try {
        return mi.proceed();
    }
    finally {
        invocation.set(oldInvocation);
    }
}

翻开源码的核心 invoke 方法,发现它在向当前线程的 ThreadLocal 中放入了当前正在执行的代理对象的方法执行包装。

每次都在增强器链的第一个执行,并且放入到线程变量ThreadLocal中。它可以让后面的增强器都拿到当前正在执行的MethodInvocation。

createProxy

所有的增强器也就都准备好了,接下来就是创建代理对象的部分了。

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
        @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    // 记录被代理bean的原始类型
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // 代理工厂的初始化
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    // 根据AOP的设计,决定是否强制使用Cglib
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            // Cglib动态代理直接记录被代理bean的所属类即可
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            // 解析被代理bean所属类的所有实现的接口
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    // 1.2.1 构造整合所有增强器
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    // 1.2.2 创建代理对象
    return proxyFactory.getProxy(getProxyClassLoader());
}

核心逻辑:
1.收集整理要织入到目标对象的通知增强器
2.创建代理对象

buildAdvisors

构建整合所有增强器:

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
    // Handle prototypes correctly...
    // 这个地方是适配Spring原生AOP的MethodInterceptor,感兴趣的小伙伴可自行研究
    Advisor[] commonInterceptors = resolveInterceptorNames();

    List<Object> allInterceptors = new ArrayList<>();
    if (specificInterceptors != null) {
        allInterceptors.addAll(Arrays.asList(specificInterceptors));
        // 组合原生的方法拦截器,共同作为AOP的通知织入
        if (commonInterceptors.length > 0) {
            if (this.applyCommonInterceptorsFirst) {
                allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
            }
            else {
                allInterceptors.addAll(Arrays.asList(commonInterceptors));
            }
        }
    }
    // logger ......

    Advisor[] advisors = new Advisor[allInterceptors.size()];
    for (int i = 0; i < allInterceptors.size(); i++) {
        // 此处有一个原生AOP的适配动作
        advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    }
    return advisors;
}

以上整合spring框架原生的AOP。

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    // Advisor增强器可以直接返回
    if (adviceObject instanceof Advisor) {
        return (Advisor) adviceObject;
    }
    // 不支持非Advice的类型
    if (!(adviceObject instanceof Advice)) {
        throw new UnknownAdviceTypeException(adviceObject);
    }
    Advice advice = (Advice) adviceObject;
    // MethodInterceptor的支持
    if (advice instanceof MethodInterceptor) {
        // So well-known it doesn't even need an adapter.
        return new DefaultPointcutAdvisor(advice);
    }
    // AdvisorAdapter的支持
    for (AdvisorAdapter adapter : this.adapters) {
        // Check that it is supported.
        if (adapter.supportsAdvice(advice)) {
            return new DefaultPointcutAdvisor(advice);
        }
    }
    throw new UnknownAdviceTypeException(advice);
}

这个方法的含义:将可以支持转换/包装为Advisor类型的对象适配成Advisor。所以方法返回的一定是Advisor。

proxyFactory.getProxy

接下来开始真正创建代理对象。

public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}

createAopProxy

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

private void activate() {
    this.active = true;
    for (AdvisedSupportListener listener : this.listeners) {
        listener.activated(this);
    }
}

getAopProxyFactory 方法返回的是当前 ProxyCreatorSupport 的成员 aopProxyFactory ,借助 Debug 可以发现它的类型是 DefaultAopProxyFactory

进入到它的 createAopProxy 方法中:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                    "Either an interface or a target is required for proxy creation.");
        }
        // 如果要代理的本身就是接口,或者已经是被jdk动态代理了的代理对象
        // 则使用jdk动态代理
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // 否则使用Cglib动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

创建完AopPorxy后,下面就是创建代理对象的动作:

AopProxy#getProxy

一下进入JdkDynamicAopProxy的getProxy方法。

public Object getProxy(@Nullable ClassLoader classLoader) {
    // logger ......
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // jdk动态代理的API
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

Proxy.newProxyInstance就是我们熟悉的代理对象的创建。

以下是Cglib的getProxy方法:

  // ......
    // Configure CGLIB Enhancer...
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
        if (classLoader instanceof SmartClassLoader &&
                ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
        }
    }
    enhancer.setSuperclass(proxySuperClass);
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
    }
    // fixedInterceptorMap only populated at this point, after getCallbacks call above
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);

    // Generate the proxy class and create a proxy instance.
    return createProxyClassAndInstance(enhancer, callbacks);
    // ......

TargetSource

AOP 的代理其实不是代理的目标对象本身,而是目标对象包装后的 TargetSource 对象。为了统一处理。

TargetSource 可以看做是目标对象 Target 的一个包装、容器,原本代理对象要执行 method.invoke(target, args) 这样的逻辑时,本来要拿到的是目标对象,但被 TargetSource 包装之后,就只能调用 method.invoke(targetSource.getTarget(), args) 这样的形式了。

public interface TargetSource extends TargetClassAware {
	Class<?> getTargetClass();
	boolean isStatic();
	Object getTarget() throws Exception;
	void releaseTarget(Object target) throws Exception;
}

SpringFramework中提供的TargetSource

1.SingletonTargetSource :每次 getTarget 都返回同一个目标对象 bean (与直接代理 target 无任何区别)

2.PrototypeTargetSource :每次 getTarget 都会从 BeanFactory 中创建一个全新的 bean (被它包装的 bean 必须为原型 bean )

3.CommonsPool2TargetSource :内部维护了一个对象池,每次 getTarget 时从对象池中取(底层使用 apache 的 ObjectPool )

4.ThreadLocalTargetSource :每次 getTarget 都会从它所处的线程中取目标对象(由于每个线程都有一个 TargetSource ,所以被它包装的 bean 也必须是原型 bean )

5.HotSwappableTargetSource :内部维护了一个可以热替换的目标对象引用,每次 getTarget 的时候都返回它(它提供了一个线程安全的 swap 方法,以热替换 TargetSource 中被代理的目标对象)

总图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值