JdkDynamicAopProxy 源码分析

原创 2018年04月14日 23:17:24

JdkDynamicAopProxy 介绍


此类是spring aop框架基于java jdk(java.lang.Proxy)代理的实现类。
JdkDynamicAopProxy实现了AopProxy接口及InvocationHandler接口

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
}

invoke方法实现


    @Override
    @Nullable
    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 {
           //spring aop不会代理equals方法。如果有。则直接使用代理类的equals()
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            //spring 代理不会代理hashcode方法。如果有hashcode。则直接使用代理类的hashCode()
            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);
            }
            //如果一个类的接口是Advised类,则spring 不会使用增强。而是直接通过反射方法进行调用
            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) {
                // Make invocation available if necessary.
                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 {
               /**
                 * 获取MethonInvocation,进行方法调用
                */
                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);
            }
        }   
    }

getInterceptorsAndDynamicInterceptionAdvice 方法实现

/**
 * 对应给定的一个java方法。获取MethodInterceptor的集合对象
 * @param method the proxied method
 * @param targetClass the target class
 * @return MethodInterceptor的集合
 */
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    //为了提高访问速度。把方法跟对应的方法拦截器链放到一个Map集合里
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        //如果缓存中不存在。则在advisorChainFactory中获取
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }
    return cached;
}

this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice实现

@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
        Advised config, Method method, @Nullable Class<?> targetClass) {
    //存放interceptor集合
    List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    //是否有introduction增强
    boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
    //Advisor适配器注册表实现。
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    //遍历所有配置的Advisor。看跟method是否匹配
    for (Advisor advisor : config.getAdvisors()) {
        //切点增强
        if (advisor instanceof PointcutAdvisor) {
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                //依据advisor适配器 把advisor转化为MethodInterceptor
                MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                //获取切点的方法匹配
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                    //如果一个MethodMatcher是runtime则创建一个新的实例。否则使用原先的实例对象
                    if (mm.isRuntime()) {
                        for (MethodInterceptor interceptor : interceptors) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        //处理Introduction增强
        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;
}

ReflectiveMethodInvocation proceed()方法实现

/**
*proceed()方法用来处理拦截器链的下一个拦截器
*/
@Override
@Nullable
public Object proceed() throws Throwable {
    //如果拦截器链为空,则直接通过反射进行方法调用
    //调用真正的被代理对象的方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }
    //遍历拦截器集合
    Object interceptorOrInterceptionAdvice =
    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

        InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        //如果方法匹配,则进行增强
        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
           //增强。并进行相应的递归调用
            return dm.interceptor.invoke(this);
        }
        else {
            //方法跟拦截器不匹配。则进行递归调用。处理下一个拦截器
            return proceed();
        }
    }
    else {
        //对Introduction进行增强处理。并进行递归调用
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

MethodInterceptor 实现举例(MethodBeforeAdviceInterceptor )

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
    private MethodBeforeAdvice advice;
    /**
     * 对MethodBeforeAdvice实现进行包装成MethodInterceptor
     * @param advice the MethodBeforeAdvice to wrap
     */
    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();
    }
}

方法反射调用

/**
 * java反射调用实现
 * @param target the target object
 * @param method the method to invoke
 * @param args the arguments for the method
 * @return the invocation result, if any
 * @throws Throwable if thrown by the target method
 * @throws org.springframework.aop.AopInvocationException in case of a reflection error
 */
@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) {
        // 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);
    }
}

Gson 使用简介

这个网页通过正常的手段是访问不到的, 为了大家能够方便的学习Gson。 因此将原文应用到此。 Overview Gson is a Java library that can be u...
  • luhuajcdd
  • luhuajcdd
  • 2012-09-12 15:23:37
  • 5188

Eclipse编写spring(4.3.9)+springMVC(4.3.9)+Mybatis(3.4.1)/Hibernate(4.3.11)+mysql(5.7)+log4j2项目

项目说明项目计划使用spring+springMVC+shiro+log4j2进行简单搭建,并完成增删改查目标,数据访问层采用 mybatis和hibernate两种方式分别与上述环境组合,适应不同...
  • u014615707
  • u014615707
  • 2017-07-17 09:25:36
  • 370

错误:'release' is unavailable: not available in automatic reference counting mode.(Xcode 4.6.2+iOS6.1)

Xcode4.6.2+iOS6.1下面编译出现错误: 'release' is unavailable: not available in automatic reference countin...
  • rena5460
  • rena5460
  • 2013-05-19 11:10:12
  • 466

做一个合格的程序猿之浅析Spring AOP源码(十五) 分析JdkDynamicAopProxy的invoke方法

上一节我们已经分析了Proxyfactorybean如何去生成一个目标对象的代理的,这一节我们将浅析一下代理的基于JDK动态代理核心的回调方法invoke的源代码 JdkDynamicAopProxy...
  • linuu
  • linuu
  • 2016-03-25 10:43:45
  • 2966

springAOP的两种方式JdkDynamicAopProxy和Cglib2AopProxy源码解析

在springAOP中,创建动态代理有两种方式,jdk的动态代理与cglib。 jdk的动态代理在springAOP中使用的是JdkDynamicAopProxy而cglib在springAOP中使用...
  • lz710117239
  • lz710117239
  • 2017-12-17 21:21:57
  • 109

完整部署CentOS7.2+OpenStack+kvm 云平台环境(1)--基础环境搭建

公司在IDC机房有两台很高配置的服务器,计划在上面部署openstack云平台虚拟化环境,用于承载后期开发测试和其他的一些对内业务。 以下对openstack的部署过程及其使用做一详细介绍,仅仅依据本...
  • kwame211
  • kwame211
  • 2017-09-15 09:05:53
  • 1162

Spring的代理模式及Spring AOP-JDKDynamicAopProxy

Reading the source of Spring AOP. The invoking flow is as the fllowing: A AbstractAutowireCapableBea...
  • luoshenhappy99
  • luoshenhappy99
  • 2010-09-08 11:46:00
  • 3298

JdkDynamicAopProxy-invoke方法-5

通过前面例子jdk动态代理生成代理对象的源码分析,已经可以很清楚的了解到代理对象是如何进行增强和回调的,接下来继续分析JdkDynamicAopProxy是如何进行回调的对目标对象进行增强的。同样,在...
  • qq_25605779
  • qq_25605779
  • 2017-07-18 23:52:42
  • 332

刨根问底Objective-C Runtime(3)- 消息 和 Category

http://chun.tips/blog/2014/11/06/bao-gen-wen-di-objective%5Bnil%5Dc-runtime(3)%5Bnil%5D-xiao-xi-he-c...
  • wqt925497045
  • wqt925497045
  • 2016-04-27 10:36:09
  • 217

Python中3+版本运行2+版本程序出现TypeError: a bytes-like object is required, not 'str'之读取PDF中的图片

Python中3+版本运行2+版本程序出现TypeError: a bytes-like object is required, not 'str'问题之提取PDF中的图片程序 问题1. 本文中出现这...
  • u014267567
  • u014267567
  • 2017-06-14 21:17:41
  • 1874
收藏助手
不良信息举报
您举报文章:JdkDynamicAopProxy 源码分析
举报原因:
原因补充:

(最多只允许输入30个字)