SpringAop源码(五)- EnableAspectJAutoProxy实现原理(调用)- invoke或者intercept(代理方法执行)

目录

一、invoke实现

1)、getInterceptorsAndDynamicInterceptionAdvice

1、MethodBeforeAdviceInterceptor

2、 AfterReturningAdviceInterceptor 

3、ThrowsAdviceInterceptor 

2)、ReflectiveMethodInvocation.proceed

二、intercept实现

三、总结


    之前已经通过一个注解开关,在ApplicationContext加载完成后,就完成了对所有连接点(切点)的Bean的解析,增强的解析,以及代理的创建。那么就是对切面进行调用了。之前分析了AnnotationAwareAspectJAutoProxyCreator在父类(AbstractAutoProxyCreator)中完成了对接口BeanPostProcessorpostProcessBeforeInstantiation方法的实现,返回的已经不是原始的Bean信息,而是代理对象。那么Spring容器拿到了代理对象,调用切入点方法时,则会调用

JdkDynamicAopProxyinvoke方法

或者

CglibAopProxyintercept方法

一、invoke实现

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 {
        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)) {
            // The target does not implement the hashCode() method itself.
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

        if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // Get as late as possible to minimize the time we "own" the target,
        // in case it comes from a pool.
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);

        // Get the interception chain for this method.
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // We need to create a method invocation...
            MethodInvocation invocation =
                    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Proceed to the joinpoint through the interceptor chain.
            retVal = invocation.proceed();
        }

        // Massage return value if necessary.
        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            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);
        }
    }
}

前面做很多的判断,调用实现自Object的hashcode方法、equals方法;以及设置了exposeProxy属性,则先将原代理对象放到一个ThreadLocal中,等到最后finally的时候,再从中remove掉。

1)、getInterceptorsAndDynamicInterceptionAdvice

List<Object> chain = this.advised
    .getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    根据当前调用方法和targetSource的Class 获取一个需要 InterceptorAndDynamicMethodMatcher(方法拦截和匹配器),结构如下:

class InterceptorAndDynamicMethodMatcher {

    final MethodInterceptor interceptor;

    final MethodMatcher methodMatcher;

    public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, 
        MethodMatcher methodMatcher) {

        this.interceptor = interceptor;
        this.methodMatcher = methodMatcher;
    }
}

之前分析过当前的this.advisored,就是ProxyFactory,获取方法如下:

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
        Advised config, Method method, @Nullable Class<?> targetClass) {

    // This is somewhat tricky... We have to process introductions first,
    // but we need to preserve order in the ultimate list.
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    Advisor[] advisors = config.getAdvisors();
    List<Object> interceptorList = new ArrayList<>(advisors.length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    Boolean hasIntroductions = null;

    for (Advisor advisor : advisors) {
        if (advisor instanceof PointcutAdvisor) {
            // Add it conditionally.
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                boolean match;
                if (mm instanceof IntroductionAwareMethodMatcher) {
                    if (hasIntroductions == null) {
                        hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                    }
                    match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                }
                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) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        else if (advisor instanceof 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;
}
Advisor[] advisors = config.getAdvisors();

就是之前分析过的:

org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR

InstantiationModelAwarePointcutAdvisorImpl类型的around增强(我们自己添加@Around的方法封装)

InstantiationModelAwarePointcutAdvisorImpl类型的after增强(我们自己添加@After的方法封装)

循环遍历,判断是否为PointcutAdvisor类型,肯定是的,再进行转型。其中需要获取拦截器和匹配器:

匹配器:MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();

拦截器:AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

              MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

获取到后new InterceptorAndDynamicMethodMatcher(拦截器,匹配器)进行返回。获取拦截器是最复杂的,下面进行梳理


    从DefaultAdvisorAdapterRegistry中进行获取,之前有说明过,无参数构造中有初始化过三个适配器,并放到内部变量adapters中,如下:

public class DefaultAdvisorAdapterRegistry implements 
    AdvisorAdapterRegistry, Serializable {

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

	public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}
}
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<>(3);
    Advice advice = advisor.getAdvice();
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {
        if (adapter.supportsAdvice(advice)) {
            interceptors.add(adapter.getInterceptor(advisor));
        }
    }
    if (interceptors.isEmpty()) {
        throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[0]);
}

上面的三个Advisor都会循环到这个方法中判断,而每个都会循环3个适配器,先判断是否supportsAdvice,再getInterceptor。以其中一个举例即可:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

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

}

判断直接用instanceOf判断,getInteceptor则是先获取传入的切面(Advisor)的增强(Advice)。再new 了不同的拦截器,则最后获取到的就是封装了传入的增强的:

MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor

每个都是一个MethodInteceptor的子类,都会实现其invoke方法,并在内部实现逻辑。

1、MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor,
    BeforeAdvice, Serializable {

    private final MethodBeforeAdvice advice;

    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }
}

执行业务逻辑(proceed)前先执行了传入的前置增强(MethodBeforeAdvice或者说其子类AspectJMethodBeforeAdvice)的before方法。就是先执行自定义的前置增强方法,再执行业务逻辑。

2、 AfterReturningAdviceInterceptor 

public class AfterReturningAdviceInterceptor implements MethodInterceptor, 
    AfterAdvice, Serializable {

	private final AfterReturningAdvice advice;

	public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}


	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		Object retVal = mi.proceed();
		this.advice.afterReturning(retVal, mi.getMethod(), 
            mi.getArguments(), mi.getThis());
		return retVal;
	}
}

当前是先执行业务逻辑,再执行传入的后置增强(AfterReturningAdvice或者说其子类AspectJAfterReturningAdvice)的before方法。

3、ThrowsAdviceInterceptor 

public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
    @Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		catch (Throwable ex) {
			Method handlerMethod = getExceptionHandler(ex);
			if (handlerMethod != null) {
				invokeHandlerMethod(mi, ex, handlerMethod);
			}
			throw ex;
		}
	}
    // ...... 省略其他的方法
}

只要是MethodInvocation的proceed方法执行,就会进行try catch,并且使用事先定义好的异常处理方法进行处理。而当前的MethodInvocation后面得知是ReflectiveMethodInvocation或者CglibMethodInvocation

2)、ReflectiveMethodInvocation.proceed方法

如果上面获取的 拦截器和匹配器链不为空:

// We need to create a method invocation...
MethodInvocation invocation =
    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();

执行方法proceed()如下:

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) {
        // Evaluate dynamic method matcher here: static part will already have
        // been evaluated and found to match.
        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.
            // Skip this interceptor and invoke the next in the chain.
            return proceed();
        }
    }
    else {
        // It's an interceptor, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

首先这一个很明显的责任链模式,并且使用传入this的方式。具体关于责任链模式可以参见责任链模式-实现和优秀源码使用分析。先根据List的长度进行判断,如果是最后一个则直接使用Spring的反射工具包,直接反射执行方法。

protected Object invokeJoinpoint() throws Throwable {
    return AopUtils.invokeJoinpointUsingReflection(this.target, 
        this.method, this.arguments);
}
public static Object invokeJoinpointUsingReflection(@Nullable Object target, 
    Method method, Object[] args) throws Throwable {

    // Use reflection to invoke the method.
    try {
        ReflectionUtils.makeAccessible(method);
        return method.invoke(target, args);
    }
    catch (InvocationTargetException ex) {
        // Invoked method threw a checked exception.
        // We must rethrow it. The client won't see the interceptor.
        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);
    }
}

如果不是最后一位,则获取InterceptorAndDynamicMethodMatcher中的MethodInterceptor执行invoke方法,并传入当前对象。知道责任链执行完成。

二、intercept实现

@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
    Object target = null;
    TargetSource targetSource = this.advised.getTargetSource();
    try {
        if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
        // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        Object retVal;
        // Check whether we only have one InvokerInterceptor: that is,
        // no real advice, but just reflective invocation of the target.
        if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
            // We can skip creating a MethodInvocation: just invoke the target directly.
            // Note that the final invoker must be an InvokerInterceptor, so we know
            // it does nothing but a reflective operation on the target, and no hot
            // swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = methodProxy.invoke(target, argsToUse);
        }
        else {
            // We need to create a method invocation...
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
        }
        retVal = processReturnType(proxy, target, method, retVal);
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

核心方法获取拦截器和匹配器都是一样的:

List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

只是后面创建的MethodInvocation为CglibMethodInvocation

// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

最后调用的proceed方法,虽然子类重写了,但主要方法还是调用父类ReflectiveMethodInvocation的,就还是责任链的处理流程。

@Override
@Nullable
public Object proceed() throws Throwable {
    try {
        return super.proceed();
    }
    catch (RuntimeException ex) {
        throw ex;
    }
    catch (Exception ex) {
        if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) {
            throw ex;
        }
        else {
            throw new UndeclaredThrowableException(ex);
        }
    }
}

三、总结

    当Spring容器启动好之后,本应该将初始化为TargetSource的Bean,在调用BeanPostProcessor接口的实现AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInitialization方法中给处理成代理对象进行返回,那么后面Spring容器中的都是代理对象,再调用还有所有连接点方法(切点)的时候,则会真正执行JdkDynamicAopProxy的invoke方法或者CglibAopProxy的intercept方法

    但是不论执行那个,都是会先根据method和Class<?>去获取 拦截器和匹配器的责任链,而根据不同的增强获取到了不同类型的拦截器,在内部已经预定了增强方法,那么在最后只要执行责任链的方法,那么所有增强方法和targetSource中的真正的方法就会按照预定的顺序进行调用。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值