spring aop 源码解读之我见
阅读原文时间:2023年07月08日阅读:5

spring aop 都是动态代理,分为jdk代理和cglib代理。默认的情况下,如果类有实现了接口,使用jdk代理。如果没有实现接口,则使用cglib代理。在下面的代码中,我会标明对应的这段代码。

和以前一样,关键代码我会标红色。

首先,分析jdk代理。之前一直找不到jdk代理的源码入口。后来网上看大神的源码分析,在结合自己写的例子,终于是发现了入口,入口的关键点,是InvocationHandler。由于jdk代理也实现了这个接口,所以也实现了自己的invoke方法。代码如下:

/**
* Implementation of {@code InvocationHandler.invoke}.
*

Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
@Override
@Nullable
//实现invoke方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
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.  
            //不实现equals方法  

            return equals(args\[0\]);  
        }  
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {  
            // The target does not implement the hashCode() method itself.  

            //不实现hasCode方法                  
            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...  

            //使用代理配置对ProxyConfig的服务调用  

            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.  
        // 检查是否有通知。如果没有,则直接反射调用目标类,不会创建方法调用(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.  
            // 允许直接执行目标类,而不创建方法调用invocation。注意,最终的调用者依然是InvokerInterceptor,尽管只是直接反射操作,没有任何的拦截。  

            Object\[\] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);     //适配器模式  
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);     //直接使用反射调用  
        }  
        else {  
            // We need to create a method invocation...   
            // 创建一个方法调用  
            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);  
        }  
    }  
}

先跟进 getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)

/**
* Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
* for the given method, based on this configuration.
* @param method the proxied method
* @param targetClass the target class
* @return a List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
//基于方法的配置,获取它的拦截器 集合。这里可以看出,拦截器 集合是一个list,放在map中,map的key则是方法名称和hascode组成

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {  
    MethodCacheKey cacheKey = new MethodCacheKey(method);  
    List<Object> cached = this.methodCache.get(cacheKey);  
    if (cached == null) {  
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(  
                this, method, targetClass);  
        this.methodCache.put(cacheKey, cached);  
    }  
    return cached;  
}

@Override
public List 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.  
    List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);  
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());  
    boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);        //检查是否有匹配配置的类  
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    for (Advisor advisor : config.getAdvisors()) {          //遍历advisor  
        if (advisor instanceof PointcutAdvisor) {            //如果是切入点的的advisor(方法级别)  
            // Add it conditionally.  
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;  
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {     //检查经过过滤的类是否还匹配advisor  
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();  
                if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {    //检查匹配的方法  
                    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;  
}

下面看下:invocation.proceed() 。这个方法真正地使拦截器起作用。代码如下:

@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) {  
        // Evaluate dynamic method matcher here: static part will already have  
        // been evaluated and found to match.  
        InterceptorAndDynamicMethodMatcher dm =  
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;  
        if (dm.methodMatcher.matches(this.method, this.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);  
    }  
}

//org\springframework\aop\framework\ReflectiveMethodInvocation.class
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { //如果是自后一个匹配的拦截器,则直接调用
return this.invokeJoinpoint(); //可以看出,这里有反射和cglig两种实现方法,也就是,对应jdk和cglib
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { //如果是匹配的拦截器&方法
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed(); //如果类的方法完全匹配,则直接执行,否则执行回调
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}

jdk和cglib其实都是一样的意思,简单看下cglib的invokeJoinPoint()

protected Object invokeJoinpoint() throws Throwable {
return this.publicMethod ? this.methodProxy.invoke(this.target, this.arguments) : super.invokeJoinpoint();
}

public Object invoke(Object obj, Object[] args) throws Throwable {
try {
this.init();
MethodProxy.FastClassInfo fci = this.fastClassInfo;
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException var4) {
throw var4.getTargetException();
} catch (IllegalArgumentException var5) {
if (this.fastClassInfo.i1 < 0) {
throw new IllegalArgumentException("Protected method: " + this.sig1);
} else {
throw var5;
}
}
}

在这里看到 fci.f1.invoke(fci.i1, obj, args)。也就是我们的拦截器织入的方法执行。这里又个有意义的现象,就是使用fci.f1.invoke ,这中fastclass的方式来执行,之所以使用这种方式,是因为cglib生成动态代理的子类的时候,已经为每一个方法增加了一个独一无二的索引,有了索引之后,这样执行会比直接调用快,具体的可以去百度下。

-------------------------------------------------------------------------------------------------

总结:spring aop的执行流程,分为两步:1、生成拦截器链  2、切入点(方法)织入代码,进行拦截

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章