首页 > 编程语言 > 详细

spring aop 源码分析(二) 代理方法的执行过程分析

时间:2020-07-09 13:06:25      阅读:70      评论:0      收藏:0      [点我收藏+]

在上一篇aop源码分析时,我们已经分析了一个bean被代理的详细过程,参考:https://www.cnblogs.com/yangxiaohui227/p/13266014.html

本次主要是分析目标方法的执行过程: 测试代码在git : https://gitee.com/yangxioahui/aopdemo.git

主要代码如下:

public interface Calc {
    Integer add(int num1,int num2);
}
@Component
public class MyMath implements Calc {

   public Integer add(int num1,int num2){
        return num1+num2;
    }

}
@Aspect
@Component
public class MyAspectJ {
    @Pointcut(" execution(* com.yang.xiao.hui.aop.MyMath.*(..))")
    private void pointcut(){}
    @Before(value = "pointcut()")
    public void before(JoinPoint joinPoint){
        System.out.println("before。。。。。");
    }
    @After(value = "pointcut()")
    public void after(JoinPoint joinPoint){
        System.out.println("after。。。。");
    }

    @AfterReturning(value = "pointcut()")
    public void afterReturning(){
        System.out.println("afterReturning。。。");
    }

    @AfterThrowing(value = "pointcut()")
    public void afterThrowing(JoinPoint joinPoint){
        System.out.println("afterThrowing。。。。");
    }

    @Around(value ="pointcut()")
    public void around(ProceedingJoinPoint joinPoint){
        System.out.println("around-before。。。。");
        try {
            Object proceed = joinPoint.proceed();
            System.out.println("around-after_return。。。");
        } catch (Throwable throwable) {
            System.out.println("around-throw。。。"+throwable.getMessage());
        }
        System.out.println("around-after。。。");
    }
}
@Configuration
@ComponentScan("com.yang.xiao.hui.aop")
@EnableAspectJAutoProxy()
public class App 
{
    public static void main( String[] args )
    {

        ApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);
        Calc myMath = (Calc)ctx.getBean("myMath");
        myMath.add(3,5);
        System.out.println(ctx.getBean("myMath").getClass());


    }
}

测试: MyMath  类的add 方法执行过程,debug 调试:

技术分享图片

 

 技术分享图片

 

 上一篇源码分析,我们已经分析过,最终会被JdkDynamicAopProxy 的invoke方法调用,下面分析下该方法:

 

@Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource; //里面封装了被代理对象,也就是MyMath
        Object target = null; //返回值

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { //处理equals方法
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { //处理Hashcode 方法
                // 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);
            }
        }
    }

 

spring aop 源码分析(二) 代理方法的执行过程分析

原文:https://www.cnblogs.com/yangxiaohui227/p/13273001.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!