【Spring】AOP实现原理(三):创建代理

【Spring】AOP实现原理(三):创建代理,第1张

AbstractAutoProxyCreator

在AbstractAutoProxyCreator的wrapIfNecessary方法中,调用getAdvicesAndAdvisorsForBean方法获取到所有的Advisor之后,就可以创建代理对象了,创建的具体过程在createProxy方法中:

  1. 创建代理工厂ProxyFactory
  2. 调用buildAdvisors构建Advisor,入参是getAdvicesAndAdvisorsForBean获取到的Advice和Advisor,里面又调用了AdvisorAdapterRegistry的wrap方法判断Advice是否是Advisor类型,这一步主要是对通知Advice进行校验,如果通知不是Advisor类型将其包装为Advisor
  3. 通过代理工厂ProxyFactory生成代理对象
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    /**
     * 是否有必要生成代理对象
     * @param bean
     * @param beanName
     * @param cacheKey
     * @return
     */
    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;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // 获取Advices和Advisors
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 创建代理,specificInterceptors就是获取到的Advices和Advisors
            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;
    }
  
    /**
     * 创建代理对象
     */
    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);
        }
        // 1.创建代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
        // 2.构建Advisor
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        // 设置Advisor
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        // 3.生成代理对象
        return proxyFactory.getProxy(getProxyClassLoader());
    }
}

构建Advisor

AbstractAutoProxyCreator的buildAdvisors主要是对通知Advice进行校验,如果通知不是Advisor类型将其包装为Advisor,具体是通过AdvisorAdapterRegistry的wrap方法实现的:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    // 调用GlobalAdvisorAdapterRegistry的getInstance获取AdvisorAdapterRegistry实例
    private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

    /**
     * 构建Advisors,specificInterceptors是上一步获取到的Advice和Advisor
     */
    protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
        // Handle prototypes correctly...
        Advisor[] commonInterceptors = resolveInterceptorNames();

        List<Object> allInterceptors = new ArrayList<>();
        if (specificInterceptors != null) {
            // 将获取到的Advice和Advisor添加到拦截器中
            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()) {
            int nrOfCommonInterceptors = commonInterceptors.length;
            int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
            logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
                    " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
        }
        // 创建Advisor集合
        Advisor[] advisors = new Advisor[allInterceptors.size()];
        for (int i = 0; i < allInterceptors.size(); i++) {
            // 调用AdvisorAdapterRegistry的wrap方法将通知包装为Advisor进行增强,在DefaultAdvisorAdapterRegistry中实现
            advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
        }
        return advisors;
    }

}

AdvisorAdapterRegistry

在GlobalAdvisorAdapterRegistry中可以看到使用的是DefaultAdvisorAdapterRegistry:

public final class GlobalAdvisorAdapterRegistry {
	/**
	 * 使用DefaultAdvisorAdapterRegistry
	 */
	private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();

	/**
	 * 返回AdvisorAdapterRegistry
	 */
	public static AdvisorAdapterRegistry getInstance() {
		return instance;
	}
}
DefaultAdvisorAdapterRegistry

DefaultAdvisorAdapterRegistry中的wrap方法主要逻辑如下:

  1. 如果当前的通知已经是Advisor类型直接返回即可
  2. 如果当前的通知不是Advice类型,抛出异常
  3. 将通知转为Advice,对通知进行判断
    • 如果通知是MethodInterceptor方法拦截器,将其包装为DefaultPointcutAdvisor
    • 如果不是MethodInterceptor,遍历Adapter适配器,找出支持当前通知的适配器,再将通知包装为DefaultPointcutAdvisor返回
  4. 非以上几种情况抛出异常
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    @Override
    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 = (Advice) adviceObject;
        // 如果是一个方法拦截器
        if (advice instanceof MethodInterceptor) {
            // 包装为DefaultPointcutAdvisor
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            // 判断Advisor适配器是否支持当前的Advice
            if (adapter.supportsAdvice(advice)) {
                // 包装为DefaultPointcutAdvisor
                return new DefaultPointcutAdvisor(advice);
            }
        }
        // 抛出异常
        throw new UnknownAdviceTypeException(advice);
    }
}
生成代理对象

上一步中已经对所有的Advice进行了校验,转为了Advisor进行增强,接下来就可以生成代理对象了,具体实现在ProxyFactory的getProxy中:

  1. 调用createAopProxy获取AopProxy,AopProxy是一个接口,定义了getProxy获取代理对象的方法,它有两个实现类分别为CglibAopProxy和JdkDynamicAopProxy

  1. 调用AopProxy的getProxy方法获取代理对象
public class ProxyFactory extends ProxyCreatorSupport {
    /**
     * 获取代理对象
     */
    public Object getProxy(@Nullable ClassLoader classLoader) {
        // 通过工厂创建AOP代理对象,createAopProxy方法在ProxyCreatorSupport中实现
        return createAopProxy().getProxy(classLoader);
    }

}
createAopProxy创建AopProxy

createAopProxy的实现逻辑在ProxyFactory的父类ProxyCreatorSupport中实现,它使用了工厂模式生成代理对象:

  1. 调用getAopProxyFactory方法获取AopProxyFactory,在无参构造函数中可以看的默认使用的工厂是DefaultAopProxyFactory
  2. 调用AopProxyFactory的createAopProxy方法创建代理对象
// ProxyCreatorSupport
public class ProxyCreatorSupport extends AdvisedSupport {

    // AOP代理工厂
    private AopProxyFactory aopProxyFactory;

    /**
     * 无参构造函数
     */
    public ProxyCreatorSupport() {
        // 工厂的实现默认使用DefaultAopProxyFactory
        this.aopProxyFactory = new DefaultAopProxyFactory();
    }

    /**
     * 带有AopProxyFactory参数的构造函数
     */
    public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
        Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
        this.aopProxyFactory = aopProxyFactory;
    }

    /**
     * 创建AopProxy
     */
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        // 1.调用getAopProxyFactory获取AopProxy,2.调用AopProxy的createAopProxy创建代理对象
        return getAopProxyFactory().createAopProxy(this);
    }

    /**
     * 返回AOP代理工厂
     */
    public AopProxyFactory getAopProxyFactory() {
        return this.aopProxyFactory;
    }
}
DefaultAopProxyFactory

DefaultAopProxyFactory中创建AOP代理的逻辑如下:

  1. 获取目标对象的Class信息
  2. 对Class进行判断:
  • **如果是一个接口或者isProxyClass返回true使用JDK动态代理生成代理对象,**isProxyClass方法在JDK的Proxy中实现,返回true的条件为目标类是java.lang.reflect.Proxy的子类并且缓存中包含目标类
  • 如果上一个条件不满足则使用CGLIB生成代理对象
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            // 获取目标对象的Class信息
            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.");
            }
            // 如果是一个接口
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            // 否则使用CGLIB生成代理对象
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }
}

// java.lang.reflect.Proxy
public class Proxy implements java.io.Serializable {

    public static boolean isProxyClass(Class<?> cl) {
        // 是否是java.lang.reflect.Proxy的子类并且缓存中包含目标类
        return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
    }
}

到此AopProxy已经创建成功,接下来以JdkDynamicAopProxy为例查看getProxy获取代理对象过程。

getProxy获取代理对象

JdkDynamicAopProxy是通过JDK的动态代理实现代理创建的,可以看到它实现了InvocationHandler接口,关于JDK的动态代理实现原理可参考【JAVA】动态代理,这里我们需要关注getProxy和invoke方法:

  • **getProxy:**创建代理对象
  • **invoke:**当代理对象中引用的方法执行时会进入这个方法中
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

    @Override
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 生成代理对象
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 先省略
        
    }
}
getProxy创建代理对象

可以看到是通过JDK中Proxy的newProxyInstance生成代理对象的:


final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 生成代理对象
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
}
invoke方法

当调用AOP中需要被通知拦截的方法时,会进入到invoke方法,比较核心的是getInterceptorsAndDynamicInterceptionAdvice获取拦截器链,如果为空直接通过反射执行目标方法即可,如果不为空,将方法包装为MethodInvocation,然后执行拦截器链:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    
    /** AdvisedSupport */
    private final AdvisedSupport advised;
    
    /**
     * InvocationHandler中定义的invoke方法,当目标方法执行时会进入到这个方法中
     * @param proxy 代理对象
     * @param method 需要被执行的目标方法
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            // 如果是equals方法
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // 如果是hashCode方法
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // 如果方法所在类是DecoratingProxy类
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;
            // 是否需要暴露代理
            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // 获取当前方法的拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 校验拦截器链是否为空
            if (chain.isEmpty()) {
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                // 如果为空直接执行目标方法即可
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // 创建MethodInvocation
                MethodInvocation invocation =
                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // 执行拦截器链
                retVal = invocation.proceed();
            }

            // 获取方法返回值
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}
获取方法的拦截器链

获取目标方法的拦截器链在AdvisedSupport中实现,它主要用于将适用于当前方法的Advisor转为方法拦截器,首先它先从缓存中查询,如果未查询到,调用advisorChainFactory方法的getInterceptorsAndDynamicInterceptionAdvice进行获取,在DefaultAdvisorChainFactory中实现:

public class AdvisedSupport extends ProxyConfig implements Advised {
    /** AdvisorChainFactory,默认使用DefaultAdvisorChainFactory*/
    AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
    /**
     * 获取方法的拦截器链
     */
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
        // 构建缓存KEY
        MethodCacheKey cacheKey = new MethodCacheKey(method);
        // 从缓存获取
        List<Object> cached = this.methodCache.get(cacheKey);
        if (cached == null) {
            // 如果未从缓存中获取到,调用getInterceptorsAndDynamicInterceptionAdvice获取方法的拦截器链
            cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                    this, method, targetClass);
            // 加入到缓存
            this.methodCache.put(cacheKey, cached);
        }
        return cached;
    }
}
DefaultAdvisorChainFactory

getInterceptorsAndDynamicInterceptionAdvice中先获取了所有的Advisor,然后遍历Advisor,对Advisor进行判断:

  1. 如果是PointcutAdvisor类型,将Advisor转为PointcutAdvisor,然后获取Pointcut切点的ClassFilter,通过matches方法判断当前方法所属的class是否匹配,如果匹配,则从切点中获取MethodMatcher方法匹配器,调用它的matches方法判断切点与当前方法是否匹配,如果也匹配,调用AdvisorAdapterRegistry的getInterceptors将Advisor转为方法拦截器

  2. 如果是引入通知IntroductionAdvisor,并且ClassFilter的matches与当前类匹配,调用AdvisorAdapterRegistry的getInterceptors将Advisor转为方法拦截器

  3. 非以上两种情况,调用AdvisorAdapterRegistry的getInterceptors将Advisor转为方法拦截器

可以看到以上三种情况,最后都是调用了AdvisorAdapterRegistry获取拦截器的,接下来就进入AdvisorAdapterRegistry中查看getInterceptors的具体实现。

public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
    /**
     * 获取方法的拦截器链
     */
    @Override
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, @Nullable Class<?> targetClass) {

        // 获取AdvisorAdapterRegistry
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        // 获取Advisor
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList<>(advisors.length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        Boolean hasIntroductions = null;
        // 遍历Advisor
        for (Advisor advisor : advisors) {
            // 如果是PointcutAdvisor类型
            if (advisor instanceof PointcutAdvisor) {
                // Add it conditionally.
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                // 调用matches方法判断与当前class是否匹配
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    // 获取方法匹配器MethodMatcher
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    boolean match;
                    // 如果是IntroductionAwareMethodMatcher
                    if (mm instanceof IntroductionAwareMethodMatcher) {
                        if (hasIntroductions == null) {
                            hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                        }
                        match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                    }
                    else {
                        // 调用MethodMatcher的matches方法匹配
                        match = mm.matches(method, actualClass);
                    }
                    if (match) {
                        // 如果匹配,从registry中获取方法拦截器
                        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));
                            }
                        }
                        else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            }
            else if (advisor instanceof IntroductionAdvisor) {
                // 如果是引入通知IntroductionAdvisor
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
            else {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }

        return interceptorList;
    }
}
DefaultAdvisorAdapterRegistry

在DefaultAdvisorAdapterRegistry的构造函数中注册了三种AdvisorAdapter,使用了适配器模式将Advisor转换为方法拦截器MethodInterceptor,三种AdvisorAdapter分别为:

  • MethodBeforeAdviceAdapter:支持前置通知MethodBeforeAdvice
  • AfterReturningAdviceAdapter:支持返回通知AfterReturningAdvice
  • ThrowsAdviceAdapter:支持ThrowsAdvice

AspectJAfterThrowingAdvice、AspectJAroundAdvice和AspectJAfterAdvice本身已经实现了MethodInterceptor接口,所以不需要进行转换:

在getInterceptors方法中,对Advisor进行判断,如果本身已经是MethodInterceptor直接返回即可,否则遍历所有的AdvisorAdapter,找出支持当前Advisor的Adapter,然后将Advisor转为MethodInterceptor:

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

    /**
     *  注册AdvisorAdapter
     */
    public DefaultAdvisorAdapterRegistry() {
        // 注册MethodBeforeAdviceAdapter
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        // 注册AfterReturningAdviceAdapter
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        // 注册ThrowsAdviceAdapter
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }
    
    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<>(3);
        // 从Advisor中获取Advice
        Advice advice = advisor.getAdvice();
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor) advice);
        }
        // 遍历Adapter
        for (AdvisorAdapter adapter : this.adapters) {
            // 判断是否支持当前的通知
            if (adapter.supportsAdvice(advice)) {
                // 通过Adapter获取拦截器
                interceptors.add(adapter.getInterceptor(advisor));
            }
        }
        if (interceptors.isEmpty()) {
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        }
        return interceptors.toArray(new MethodInterceptor[0]);
    }
}

AdvisorAdapter有三个实现类,以MethodBeforeAdviceAdapter为例查看一下supportsAdvice和getInterceptor的实现:

  1. 在supportsAdvice方法中可以看到它支持的是MethodBeforeAdvice方法前置通知

  2. 在getInterceptor方法中,首先从Advisor中获取到了通知,然后将通知封装为MethodBeforeAdviceInterceptor返回

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
        // 是否是MethodBeforeAdvice类型
        return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        // 封装为MethodBeforeAdviceInterceptor
        return new MethodBeforeAdviceInterceptor(advice);
    }

}
执行目标方法

回顾invoke方法中的主要逻辑,在获取到方法的拦截器之后,对拦截器是否为空进行了判断:

  • 如果为空,调用AopUtils的invokeJoinpointUsingReflection通过反射直接执行方法即可

  • 如果不为空创建MethodInvocation,具体实现类是ReflectiveMethodInvocation,然后调用proceed执行拦截器链


    // 获取当前方法的拦截器链
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    // 校验拦截器链是否为空
    if (chain.isEmpty()) {
        Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
        // 如果为空直接执行目标方法即可
        retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
    } else {
        // 创建MethodInvocation,使用的是ReflectiveMethodInvocation类型
        MethodInvocation invocation =
                new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
        // 执行拦截器链
        retVal = invocation.proceed();
    }
invokeJoinpointUsingReflection

invokeJoinpointUsingReflection方法通过反射执行目标方法,在AopUtils中实现:

public abstract class AopUtils {

    @Nullable
    public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
            throws Throwable {

        // 通过反射执行目标方法
        try {
            ReflectionUtils.makeAccessible(method);
            return method.invoke(target, args);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                    method + "] on target [" + target + "]", ex);
        }
        catch (IllegalAccessException ex) {
            throw new AopInvocationException("Could not access method [" + method + "]", ex);
        }
    }

}
proceed方法执行拦截器链

因为拦截器可以有多个,所以proceed方法是一个递归调用的过程,currentInterceptorIndex记录了当前拦截器的下标:

  1. 判断currentInterceptorIndex是否与拦截器链的大小一致,如果一致说明已经走到了最后一个拦截器,调用invokeJoinpoint方法执行目标方法即可,可以看到调用了AopUtils的invokeJoinpointUsingReflection通过反射执行目标方法,如果不是最后一个拦截器进入第2步
  2. 对currentInterceptorIndex++,获取下一个拦截器,判断拦截器是否是InterceptorAndDynamicMethodMatcher类型,如果是获取methodMatcher对目标方法进行匹配:
    • 如果与目标方法匹配成功,执行拦截器的invoke方法
    • 如果与目标方法匹配不成功,递归调用proceed方法执行下一个拦截器
  3. 如果拦截器不是InterceptorAndDynamicMethodMatcher类型,直接调用方法拦截器MethodInterceptor的invoke执行拦截器即可

在执行MethodInterceptor方法拦截器的invoke方法时,传入的参数是this,指的是ReflectiveMethodInvocation对象本身,在拦截器方法执行后需要拿到这个对象调用proceed方法继续执行下一个拦截器,可以看到这里使用了责任链模式,对拦截器进行一个个的调用。

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
    @Override
    @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();
        }
        // 获取下一个拦截器
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // 如果是InterceptorAndDynamicMethodMatcher
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            // 判断方法是否匹配
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // 如果方法不匹配,跳过当前拦截器执行下一个,递归调用
                return proceed();
            }
        }
        else {
            // 转为MethodInterceptor执行拦截器,注意invoke传入的参数是this,指的是ReflectiveMethodInvocation对象本身,在拦截器的invoke方法中需要拿到这个对象调用proceed方法继续执行下一个拦截器
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

    /**
     * 通过反射执行目标方法
     */
    @Nullable
    protected Object invokeJoinpoint() throws Throwable {
        return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }

}

MethodBeforeAdviceInterceptor

以前置通知为例,看一下MethodBeforeAdviceInterceptor拦截器中的invoke方法的执行逻辑:

  1. 前置通知是在目标方法执行之前执行的方法,所以先调用了invokeAdviceMethod执行了前置通知方法
  2. 调用MethodInvocation的proceed执行下一个拦截器链,在上一步中可以看到调用拦截器时传入的是this,this指向ReflectiveMethodInvocation,所以会继续执行到它的proceed方法,继续下一个拦截器的执行
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 先执行通知方法,在AspectJMethodBeforeAdvice中实现
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        // 执行拦截器链,这里调用的是MethodInvocation的proceed方法,会再次进入到ReflectiveMethodInvocation的proceed方法中
        return mi.proceed();
    }

}
// AspectJMethodBeforeAdvice
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        // 执行通知方法
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
}

AspectJAroundAdvice

再以环绕通知为例,看一下环绕通知的执行逻辑,AspectJAroundAdvice实现了MethodInterceptor接口,所以它本身就是一个拦截器,在invoke方法中它调用了invokeAdviceMethod执行通知方法,并将ReflectiveMethodInvocation转换为ProceedingJoinPoint,在环绕通知中通过ProceedingJoinPoint调用proceed方法执行下一个拦截器:

public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        }
        // mi是上一步中传入的ReflectiveMethodInvocation,这里将其转换为ProxyMethodInvocation
        ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
        // 将ProxyMethodInvocation转为ProceedingJoinPoint
        ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
        JoinPointMatch jpm = getJoinPointMatch(pmi);
        // 执行通知方法
        return invokeAdviceMethod(pjp, jpm, null, null);
    }
}

@SuppressWarnings("serial")
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
    /**
     * 执行通知方法
     */
    protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
                                        @Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
        // 通过给定的参数执行通知方法
        return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
    }
    /**
     * 通过给定的参数执行通知方法
     */
    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterCount() == 0) {
            actualArgs = null;
        }
        try {
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            // 这里执行了通知方法,接下来会进入到定义的环绕通知方法中
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" +
                    this.aspectJAdviceMethod + "]; pointcut expression [" +
                    this.pointcut.getPointcutExpression() + "]", ex);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}

假设定义了如下的环绕通知,在环绕通知方法被执行时,会进入到logAroudAdvice方法中,可以看到先打印了方法执行前的日志,然后调用了ProceedingJoinPoint的proceed方法执行拦截器链,上一步可知ProceedingJoinPoint是MethodInvocation转换而来,所以又会进入到ReflectiveMethodInvocation的proceed方法执行下一个拦截器链,待所有的拦截器执行完毕后proceed方法也就结束,然后执行了printAfterLog打印方法执行后的日志:

    /**
     * 通知Advice,这里使用了环绕通知
     * @param joinPoint 连接点
     * @return
     * @throws Throwable
     */
    @Around("logPoiontcut()") // 引用切点
    public Object logAroudAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // 方法执行前的日志打印
        printBeforeLog(joinPoint);
        // 执行拦截器链
        Object returnValue = joinPoint.proceed();
        // 方法执行后的日志打印
        printAfterLog(returnValue);
        return returnValue;
    }
总结

方法拦截器链的执行流程图

AOP总结

参考

【猫吻鱼】Spring源码分析:全集整理

Spring版本:5.2.5.RELEASE

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/905644.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-15
下一篇 2022-05-15

发表评论

登录后才能评论

评论列表(0条)

保存