Back to Javatutorial

SpringAop(四):Jdk动态代理

docs/Spring全家桶/Spring源码分析/SpringAOP/SpringAop(四):jdk动态代理.md

1.0.022.2 KB
Original Source

һƪµǷ spring ڴ˴дķʽΪ jdk̬ cglibǽ spring Ķ̬

1. jdk ̬

spring Ķ̬ǰ˽ jdk Ķ̬jdk ̬ҪӿڣΪ׼ӿڣ

IJdkDynamicProxy01

java
package org.springframework.learn.demo03;

public interface IJdkDynamicProxy01 {
    void hello01();
}

IJdkDynamicProxy02

java
package org.springframework.learn.demo03;

public interface IJdkDynamicProxy02 {
    void hello02();
}

׼ʵࣺ

JdkDynamicProxyImpl01

java
package org.springframework.learn.demo03;

public class JdkDynamicProxyImpl01 implements IJdkDynamicProxy01, IJdkDynamicProxy02{
    @Override
    public void hello01() {
        System.out.println("hello01");
    }

    @Override
    public void hello02() {
        System.out.println("hello02");
    }
}

JdkDynamicProxyImpl02

java
package org.springframework.learn.demo03;

public class JdkDynamicProxyImpl02 implements IJdkDynamicProxy01 {

    @Override
    public void hello01() {
        System.out.println("hello01");
    }

}

ҪעǣJdkDynamicProxyImpl01 ʵ IJdkDynamicProxy01 IJdkDynamicProxy02 ӿڣJdkDynamicProxyImpl02 ֻʵ IJdkDynamicProxy01 һ ӿڡ

׼һ InvocationHandler:

MyInvocationHandler

java
package org.springframework.learn.demo03;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

     /** Ŀ */
     private Object target;

    public MyInvocationHandler(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("ִзΪ:" + method.getName());
        // ִ
        Object rs = method.invoke(target,args);
        return rs;
    }

}

:

java
package org.springframework.learn.demo03;

import java.lang.reflect.Proxy;

public class Demo03Main {

    public static void main(String[] args) {
        System.out.println("------------bean01------------");
        JdkDynamicProxyImpl01 bean01 = new JdkDynamicProxyImpl01();
        Object obj1 = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                // JdkDynamicProxyImpl01ʵ IJdkDynamicProxy01, IJdkDynamicProxy02
                // classΪ IJdkDynamicProxy01, IJdkDynamicProxy02
                new Class<?>[]{ IJdkDynamicProxy01.class, IJdkDynamicProxy02.class },
                new MyInvocationHandler(bean01));
        // Խǿת
        ((IJdkDynamicProxy01) obj1).hello01();
        ((IJdkDynamicProxy02) obj1).hello02();

        System.out.println("------------bean01------------");
        Object obj2 = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                 // JdkDynamicProxyImpl01ʵ IJdkDynamicProxy01, IJdkDynamicProxy02
                 // classΪ IJdkDynamicProxy01
                 new Class<?>[]{ IJdkDynamicProxy01.class },
                 new MyInvocationHandler(bean01));
        ((IJdkDynamicProxy01) obj2).hello01();
        // 쳣java.lang.ClassCastException: class com.sun.proxy.$Proxy1 cannot be cast to class xxx
        //((IJdkDynamicProxy02) obj2).hello02();

        System.out.println("-----------bean02-------------");
        JdkDynamicProxyImpl02 bean02 = new JdkDynamicProxyImpl02();
        Object obj3 = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                 // JdkDynamicProxyImpl01ʵ IJdkDynamicProxy01
                 // classΪ IJdkDynamicProxy01, IJdkDynamicProxy02
                 new Class<?>[]{ IJdkDynamicProxy01.class, IJdkDynamicProxy02.class },
                 new MyInvocationHandler(bean02));
        ((IJdkDynamicProxy01) obj3).hello01();
        IJdkDynamicProxy02 proxy02 = (IJdkDynamicProxy02) obj3;
        // 쳣java.lang.IllegalArgumentException: object is not an instance of declaring class
        //proxy02.hello02();

    }
}

н

ִзΪ:hello01
hello01
ִзΪ:hello02
hello02
------------bean01------------
ִзΪ:hello01
hello01
-----------bean02-------------
ִзΪ:hello01
hello01

Խ£

  1. Proxy#newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) ĵڶĽӿڣǴĽӿִִͣΪ invoke()
  2. JdkDynamicProxyImpl01 ͬʱʵ IJdkDynamicProxy01 IJdkDynamicProxy02 ӿڣӿʱֻ IJdkDynamicProxy01 obj2 ǿתΪ IJdkDynamicProxy02 ʱͻᱨ ClassCastExceptionǿתʧܣ Proxy#newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) ǴĽӿͣ
  3. JdkDynamicProxyImpl02 ֻʵ IJdkDynamicProxy01 ӿڣӿʱ IJdkDynamicProxy01 IJdkDynamicProxy02 obj3 ǿתΪ IJdkDynamicProxy02 ʱδ쳣ִ proxy02.hello02() ʱȴ java.lang.IllegalArgumentException: object is not an instance of declaring classͬ Proxy#newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) ǴĽӿͣĿ޹ء

2. ٴη spring jdk ̬Ĵ

ķ spring δģ

java
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    // ȡĿʵֵĽӿ
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    // Ƿequals()hashCode()
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    //  jdk  
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
  1. ĽӿΪ proxiedInterfacesֵĿʵֵнӿڣͬʱ spring ҲĽӿڣ SpringProxy``AdvisedЩһƪѾϸˣ
  2. ָ InvocationHandler Ϊ thisҲ JdkDynamicAopProxy Ķʵ JdkDynamicAopProxy ʵ InvocationHandler.

ɵһֵķ֪jdk ̬ķ java.lang.reflect.InvocationHandler#invoke ִеģҲ JdkDynamicAopProxy#invokeǾ JdkDynamicAopProxy#invoke spring ִдġ

3. jdk ִ̬

spring jdk ִ̬ JdkDynamicAopProxy#invoke

JdkDynamicAopProxy#invoke

java
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)) {
            return equals(args[0]);
        }
        // ִе hashCode Ҫִ
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            return hashCode();
        }
        // ִеclassDecoratingProxyҲҪִ
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            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;

        // ж advisedexposeProxy ֵǷΪ true
        // advisedexposeProxyԴ @EnableAspectJAutoProxy  exposeProxy
        //  ָʱ@EnableAspectJAutoProxy(exposeProxy = true)´ִ
        if (this.advised.exposeProxy) {
            // ǰ proxy ŵ threadLocal 
            //  (UserService (AopContext.currentProxy)).getUser() ʽ
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // ȡĿĿclass
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);

        //  aop  advisor תΪжϸ÷ʹЩ淽
        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 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(...);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

Ϸ£

  1. жҪִеķǷΪ equals``hashcode ȣЩҪ
  2. ȡҪִеķ淽õһϣ
  3. 淽뼰Ŀ귽

صע淽Ŀ귽ִУؼ£

java
//  aop  advisor תΪжϸ÷ʹЩ淽
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(
        method, targetClass);
// һö
MethodInvocation invocation =
       new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// ִУص
retVal = invocation.proceed();

ȡ MethodInterceptor

ڷִǰ getInterceptorsAndDynamicInterceptionAdvice(...)ȡִе淽ģҲ MethodInterceptor

AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice

java
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;
}
java
/**
 * ȡ Interceptor£
 */
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
        Advised config, Method method, @Nullable Class<?> targetClass) {
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    // ȡ advisorsaopadvisors£
    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) {
        // advisorPointcutAdvisorʹPointcutAdvisorPointcutƥ
        if (advisor instanceof PointcutAdvisor) {
            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) {
                    // AdvisorתΪMethodInterceptor
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    if (mm.isRuntime()) {
                        for (MethodInterceptor interceptor : interceptors) {
                            //  interceptormethodMatcherװInterceptorAndDynamicMethodMatcher
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        else if (advisor instanceof IntroductionAdvisor) {
            // жΪIntroductionAdvisor͵Advisor򽫵װΪInterceptor
            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        else {
            // ṩʹԶתAdvisorת߼ΪgetInterceptors()
            // ʹӦAdapterĿAdvisorƥ䣬ƥϣͨgetInterceptor()
            // ԶAdviceתΪMethodInterceptor
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }
    return interceptorList;
}

ǸϷܽ»ȡ MethodInterceptor Ĺ̹£

  1. ȡĿе advisors

  2. ÿ

    advisor
    

̴

  1. advisor PointcutAdvisorʹе Pointcut ƥ䣬ƥɹ󣬻ȡ MethodInterceptor أ
  2. advisor IntroductionAdvisorʹе ClassFilter ƥ䣬ƥɹ󣬻ȡ MethodInterceptor أ
  3. 㣬ֱӻȡ MethodInterceptor أ

ô MethodInterceptor λȡأǼ¿

java
//  AdvisorAdapter ĵط
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

//  adapter
public DefaultAdvisorAdapterRegistry() {
    // @Before
    registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
    // @AfterReturning
    registerAdvisorAdapter(new AfterReturningAdviceAdapter());
    // @AfterThrowing
    registerAdvisorAdapter(new ThrowsAdviceAdapter());
}

/**
 * ȡadvisorӦMethodInterceptor
 */
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<>(3);
    // ȡǰadvisorMethodInterceptor
    Advice advice = advisor.getAdvice();
    //  advice  MethodInterceptorʵ
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    // 
    // ʹ AdvisorAdapter  advice תΪ MethodInterceptor
    // adviceadapter adapter.getInterceptor ȡ MethodInterceptor
    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]);
}

ܽ£

  1. advice MethodInterceptorֱӽת MethodInterceptor
  2. ϲ㣬ʹ AdvisorAdapter advice ת MethodInterceptor.

adaptersspring Ϊṩ Adapter

  • MethodBeforeAdviceAdapter @Before
  • AfterReturningAdviceAdapter @AfterReturning
  • ThrowsAdviceAdapter @AfterThrowing

Adapter ֻһܣ advice Ӧ MethodInterceptor MethodBeforeAdviceAdapter Ĵˣ

java
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
    /**
     * Ƿܴǰadvice
     */
    @Override
    public boolean supportsAdvice(Advice advice) {
        return (advice instanceof MethodBeforeAdvice);
    }

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

Adapter ĹܼƣͲˣܽ¸עӦ advice``methodInterceptor

עadvicemethodInterceptor
@BeforeAspectJMethodBeforeAdviceMethodBeforeAdviceInterceptor
@AfterAspectJAfterAdviceAspectJAfterAdvice
@AroundAspectJAroundAdviceAspectJAroundAdvice
@AfterReturningAspectJAfterReturningAdviceAfterReturningAdviceInterceptor
@AfterThrowingAspectJAfterThrowingAdviceThrowsAdviceInterceptor

ReflectiveMethodInvocation#proceed

ȡ MethodInterceptor 󣬾Ϳʼзִˣֱӽ ReflectiveMethodInvocation#proceed

java
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;
        Class<?> targetClass = (this.targetClass != null 
                ? this.targetClass : this.method.getDeclaringClass());
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
            // ƥ䣬͵ķҲ淽
            //  MethodInterceptor#invokeٴ ReflectiveMethodInvocation#proceedֵ˵ǰ
            return dm.interceptor.invoke(this);
        }
        else {
            // ƥ䣬ݹõǰ
            return proceed();
        }
    }
    else {
        // ע⣬IJ thisʾǰ
        //  MethodInterceptor#invokeٴ ReflectiveMethodInvocation#proceedֵ˵ǰ
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

/**
 * Ŀ귽
 */
protected Object invokeJoinpoint() throws Throwable {
    // ʹ÷Ŀ󷽷עﴫӦĿ󣬶Ǵ
    return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}

ϴĵʹģʽִ߼£

  1. жǷִе淽ǣִĿ귽ִһ
  2. ȡһжִܷУܣִе һ

߼ͦ򵥣ôִеأ spring У֪ͨͣ@Before``@After``@AfterReturning``@AfterThrowing @Aroundһһ֪ͨεõġ

1. @Before

MethodBeforeAdviceInterceptor#invoke

java
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    // ִǰ֪ͨ
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    // ִһ
    return mi.proceed();
}

advice.before(xxx)

AspectJMethodBeforeAdvice#before

java
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
    invokeAdviceMethod(getJoinPointMatch(), null, null);
}

ȥ

AbstractAspectJAdvice#invokeAdviceMethod(JoinPointMatch, Object, Throwable)

java
protected Object invokeAdviceMethod(
         @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
         throws Throwable {

     return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}

/**
  *  ÷ִ
  */
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
    Object[] actualArgs = args;
    if (this.aspectJAdviceMethod.getParameterCount() == 0) {
        actualArgs = null;
    }
    try {
        // Ϥjdk
        ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
        return this.aspectJAdviceMethod.invoke(
                this.aspectInstanceFactory.getAspectInstance(), actualArgs);
    }
    catch (...) {
        ...
}

Կǵ jdk õġ

2. @After

AspectJAfterAdvice#invoke

java
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        // ִһ
        return mi.proceed();
    }
    finally {
        // 淽 finally 飬ʾһִУҲʹ÷
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
}

3. @AfterReturning

AfterReturningAdviceInterceptor#invoke

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

AspectJAfterReturningAdvice#afterReturning

java
public void afterReturning(@Nullable Object returnValue, Method method, 
            Object[] args, @Nullable Object target) throws Throwable {
    if (shouldInvokeOnReturnValueOf(method, returnValue)) {
        // 淽Ȼǵ÷ִ
        invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
    }
}

4. @AfterThrowing

AspectJAfterThrowingAdvice#invoke

java
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        //  ReflectiveMethodInvocation#proceed
        return mi.proceed();
    }
    catch (Throwable ex) {
        if (shouldInvokeOnThrowing(ex)) {
            // 淽ֻ׳쳣ʱŻᱻ
            invokeAdviceMethod(getJoinPointMatch(), null, ex);
        }
        throw ex;
    }
}

5. @Around

AspectJAroundAdvice#invoke

java
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    if (!(mi instanceof ProxyMethodInvocation)) {
        throw new IllegalStateException(...);
    }
    ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
    ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
    JoinPointMatch jpm = getJoinPointMatch(pmi);
    // 淽
    return invokeAdviceMethod(pjp, jpm, null, null);
}

ʵֻ֪ͨʱһʵ֣

java
@Around(xxx)
public Object around(ProceedingJoinPoint p){
    // ִĿ귽ǰIJ
    ...

    // ִĿ귽һǹؼ
    // ʵﲢִĿ귽յõ ReflectiveMethodInvocation#proceed
    // ִһִĿ귽
    Object o = p.proceed();

    // ִĿ귽IJ
    ...
    return o;
}

spring ִ֪ͨУҪΪ֣

  1. ʹ÷䷽ʽִ淽Ҳν ǿ
  2. ReflectiveMethodInvocation#proceed ִһִĿ귽

ֵIJִдִеλã

  • @Before ֪ͨ1 ǰ2 ں
  • @AfterReturning ֪ͨ2 ǰ1 ںִ 2 ʱ쳣1 Ͳִˣ
  • @AfterThrowing ֪ͨ2 ǰ1 ں 1 Ƿ catch ִУֻз쳣1 ŻִУ
  • @After ֪ͨ2 ǰ1 ں1 Ƿ finally ִУ finally ԣʹ쳣1 ִͬУ
  • @Around ֪ͨ淽ָ 2 ִʱ

ע @AfterReturning``@AfterThrowing @After ִ֪ͨʱ

⼸ִ֪ͨеġ

ͨԵķʽ spring ִ֪ͨ˳£

  1. ִ @AfterThrowing ֪ͨȵ mi.proceed() ִһȻ catch ִ淽ֻг쳣ʱ淽ŻִУ
  2. һУ mi.proceed() ʱִ @AfterReturning ִ֪ͨʱȵ mi.proceed() ִһȻִ淽
  3. һУ mi.proceed() ʱִ @After ִ֪ͨʱȵ mi.proceed() ִһȻ finally ִ淽ʹ쳣淽ǻִУ
  4. һУ mi.proceed() ʱִ @Around ִ֪ͨʱֱִ淽 @Around ֪ͨ淽 ProceedingJoinPoint#proceed()ջǻִһ
  5. һУ mi.proceed() ʱִ @Before ִ֪ͨʱִ淽ٵ mi.proceed() ִһ
  6. ִе󣬷ûпִеˣʱͿʼִĿ귽

ͼʾִ֪ͨй£

յִ˳

4. ܽ

Ҫ jdk ִ̬й̣˸ִ֪ͨ˳򡣱ľȵˣһƪ½ cglib ִй̡


ԭӣhttps://my.oschina.net/funcy/blog/4696654 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע