(八)关于spring aop的实现细节(如何实现的各种Advice)

(七)重点看了spring aop的各个主要接口的定义,以及简单分析了各个主要方法的作用,
这节主要了解spring是怎么利用jdk\cglib 来实现的前置通知、环绕通知等等
通过(七)中查看AbstractAutoProxyCreator类时,可以知道spring创建代理对象是通过ProxyFactory来创建的。
那么这里就从ProxyFactory开始

1、查看分析spring创建Aop的工厂类ProxyFactory,及其相关父类(Aop配置类)

首先查看该类的相关的类图如下

这里写图片描述

ProxyConfig 管理创建proxy的基本陪配置
TargetClassAware 定义了获取proxy目标对象class对象的方法
Advised主要是定义了与配置代理对象的通知相关的一些方法
AdvisedSupport是对Advised接口的实现类,实现配置管理Advicor
ProxyCreatorSupport 实现创建proxy对象
ProxyFactory 对编程式aop代理创建的支持
ProxyFactoryBean 对基于BeanFactory的aop代理创建的支持
            (与编程式aop类似,主要是提供面向配置支持,结合bean容器对FactoryBean的支持,就像直接操作代理对象一样)
AspectJProxyFactory spring对解析基于aspectj风格的方面配置来创建代理对象的支持

下面是ProxyConfig中定义的配置
public class ProxyConfig implements Serializable {

    //是否是对目标类做代理(spring aop利用该配置决定是使用cglib还是jdk动态代理)
    private boolean proxyTargetClass = false;

    //是否尝试最佳化配置
    private boolean optimize = false;

    //是否非透明化处理(是否不暴露aop配置)
    boolean opaque = false;

    //是否给目标方法暴露代理对象Aop
    boolean exposeProxy = false;

    //冻结配置
    private boolean frozen = false;
}
通过该类定义的内容可以看到,ProxyConfig 应该是主要负责管理创建proxy需要的一些配置信息
public interface TargetClassAware {

    @Nullable
    Class<?> getTargetClass();

}
在对目标进行创建代理时jdk是基于接口、cglib是基于目标class对象
TargetClassAware 用来获取proxy目标类class对象,可以用来创建代理对象使用
public interface Advised extends TargetClassAware {

    boolean isFrozen();

    boolean isProxyTargetClass();

    Class<?>[] getProxiedInterfaces();

    boolean isInterfaceProxied(Class<?> intf);

    void setTargetSource(TargetSource targetSource);

    TargetSource getTargetSource();

    void setExposeProxy(boolean exposeProxy);

    boolean isExposeProxy();

    void setPreFiltered(boolean preFiltered);

    boolean isPreFiltered();

    Advisor[] getAdvisors();

    void addAdvisor(Advisor advisor) throws AopConfigException;

    void addAdvisor(int pos, Advisor advisor) throws AopConfigException;

    boolean removeAdvisor(Advisor advisor);

    void removeAdvisor(int index) throws AopConfigException;

    int indexOf(Advisor advisor);

    boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;

    void addAdvice(Advice advice) throws AopConfigException;

    void addAdvice(int pos, Advice advice) throws AopConfigException;

    boolean removeAdvice(Advice advice);

    int indexOf(Advice advice);

    String toProxyConfigString();

}
从接口中的方法可以看出,Advised主要是定义了与配置代理对象的通知相关的一些方法


AdvisedSupport的代理这里就不贴出来了,它主要是继承ProxyConfig并实现了通知相关的配置功能,为下面代理创建提供基本的配置支持。
public class ProxyCreatorSupport extends AdvisedSupport {
    //...
    public ProxyCreatorSupport() {
        this.aopProxyFactory = new DefaultAopProxyFactory();
    }
    //...
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }
    //...
}
实际创建aop代理对象的逻辑是在DefaultAopProxyFactory中实现的。

在这几个类和接口中主要是定义了aop代理创建的配置信息。
下面查看AopProxyFactory看具体创建代理对象的逻辑

2、代理对象工厂AopProxyFactory

AopProxyFactory接口中就定义了一个工厂方法,
AdvisedSupport 属于aop创建的配置,统一返回AopProxy
public interface AopProxyFactory {

    AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

}
下面查看AopProxy接口的定义
public interface AopProxy {
    //创建代理对象
    Object getProxy();
    //指定类加载器来创建代理对象
    Object getProxy(@Nullable ClassLoader classLoader);
}
从AopProxy接口定义的方法可以看出,
AopProxyFactory并不是创建代理对象的工厂,而是创建代理对象工厂的工厂。
AopProxy才是代理对象的工厂

查看AopProxyFactory的实现类DefaultAopProxyFactory
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                //目标是接口或者jdk代理类 使用jdk创建代理
                return new JdkDynamicAopProxy(config);
            }
            //使用cglib创建代理
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            //使用jdk创建代理
            return new JdkDynamicAopProxy(config);
        }
    }

    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    }

}

3、用来创建代理对象的AopProxy

至此就能看到spring是怎么利用cglib、jdk动态代理 来实现 (七)中提到的各种方面的了。

首先从较为熟悉的JdkDynamicAopProxy开始
从JdkDynamiAopProxy实现的接口上可以看出,该类不光是定义了创建Aop代理对象,而且还是代理对象的执行处理器(java.lang.reflect.InvocationHandler)
熟悉jdk代理的话,可以知道InvocationHandler会在代理对象执行目标接口的方法时去直接调用invocationHandler.invoke(..)方法
如果要进行aop编程则直接在invoke实现方法中定义自己的方面即可,因此如果想要知道spring的方面是怎么实现的,直接看invoke方法即可。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    //...
    @Override
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        //这里会为目标对象引入一些附加接口①
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        //创建代理对象
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    //...
    @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 {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                //如果目标未实现equals方法使用,统一使用这里定义的equals
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                //同equals
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                // 代理实现的decoratingProxy.getDecoratedClass() 用来获取代理目标的class对象
                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...
                // 如果在前面的aop基本配置中配置了opaque = false(透明化aop配置),这里对所有Advised接口中定义的方法都可以使用代理对象调用获取到aop的配置
                // 连接点调用 实际就是使用反射调用方法method.invoke(target, args)
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            // 下面是非特殊方法的调用
            Object retVal;

            //通过这一步可以看到exposeProxy 的作用是可以通过AopContext在方法内部调用AopContext.currentProxy() 获取当前方法的代理对象
            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.
            // targetSource.getTarget()获取的就是代理目标对象
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // Get the interception chain for this method.
            // 通过目标类和方法,来获取对应的方面
            // 这里会设置到切入点的判断PointcutAdvisor IntroductionAdvisor ...
            // 如pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)...  然后获取符合当前方法的Advisor
            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);
                // 没有匹配到对应的advisor就直接执行目标方法
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // We need to create a method invocation...
                // 要执行的目标方法就是一个连接点,这里就是将方法包装成连接点,而方面Advisors也直接包装进去了,这样方面的执行就委托给了这个连接点来实现了
                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.
            // 如果目标方法返回值是this 这里进行特殊处理了一下,防止直接返回了目标对象,将返回值替换为代理对象
            // RawTargetAccess是类型标记接口,如果目标对象实现了该方法则直接返回代理目标对象
            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.
                // 这个是aop嵌套调用时满足各层都能正确得到当前方法的代理对象
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
    //...

}
下面查看ReflectiveMethodInvocation.proceed()部门的代码,了解连接点调用(实际上是方面 + 连接点调用)
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
    //...
    protected ReflectiveMethodInvocation(
            Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
            @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

        this.proxy = proxy;
        this.target = target;
        this.targetClass = targetClass;
        this.method = BridgeMethodResolver.findBridgedMethod(method);
        this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
        //方面Advisors
        this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
    }
    //...
    @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);
        // 这里是对动态aop的支持(根据方法入参 决定是否执行方面)
        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);
        }
    }
    //...
}
这里利用方法递归来实现方面的执行的,时序图如下(假设只有两个Interceptor)。

这里写图片描述

可以看到这种递归调用 都是基于ReflectiveMethodInvocation中的proceed方法的,等于是它来负责处理递归逻辑,而对于自定义的Interceptor只需要关注
实现方面逻辑,无需维护递归逻辑。


cglib创建代理对象的过程与jdk动态代理类似
class CglibAopProxy implements AopProxy, Serializable {
    //...
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
        }

        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            //如果代理目标类已经是cglib的代理类,获取父类进行代理
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.
            validateClassIfNecessary(proxySuperClass, classLoader);

            // Configure CGLIB Enhancer...
            // 用来创建cglib代理子类的核心类,类似于jdk的Proxy
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            //配置代理目标类
            enhancer.setSuperclass(proxySuperClass);
            //要代理的接口
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
            //cglib的代理回调方法 类似于jdk的InvocationHandler 不过Callback只是一个标记接口,并未定义任何方法,其子接口定义了各种类型的回调形式
            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            // 设置过滤器,相当于spring的pointcut 用来匹配目标方法来决定是否创建代理子类方法
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // Generate the proxy class and create a proxy instance.
            // 生成代理对象实例
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                    this.advised.getTargetClass() + "]: " +
                    "Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }
    //...
    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        // Parameters used for optimization choices...
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isFrozen = this.advised.isFrozen();
        boolean isStatic = this.advised.getTargetSource().isStatic();

        // Choose an "aop" interceptor (used for AOP calls).
        // 该类实现的是org.springframework.cglib.proxy.MethodInterceptor 与jdk的InvocationHandler中的invoke方法类似,属于代理方法的回调
        // DynamicAdvisedInterceptor实现与上面jdk的JdkDynamicAopProxy中invoke方法实现类似,用来实现方面以及连接点调用
        // 这里主要是实现的spring aop
        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

        // Choose a "straight to target" interceptor. (used for calls that are
        // unadvised but can return this). May be required to expose the proxy.
        Callback targetInterceptor;
        if (exposeProxy) {
            targetInterceptor = isStatic ?
                    new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                    new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
        }
        else {
            targetInterceptor = isStatic ?
                    new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                    new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
        }

        // Choose a "direct to target" dispatcher (used for
        // unadvised calls to static targets that cannot return this).
        Callback targetDispatcher = isStatic ?
                new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
        //对于上面给enhancer设置的CallbackFilter spring分别定义了几个数字来表示对应哪个Interceptor
        //private static final int AOP_PROXY = 0;
        //rivate static final int INVOKE_TARGET = 1;
        //private static final int NO_OVERRIDE = 2;
        //private static final int DISPATCH_TARGET = 3;
        //private static final int DISPATCH_ADVISED = 4;
        //private static final int INVOKE_EQUALS = 5;
        //private static final int INVOKE_HASHCODE = 6;
        //与下面这几个一一对应
        Callback[] mainCallbacks = new Callback[] {
                aopInterceptor,  // for normal advice
                targetInterceptor,  // invoke target without considering advice, if optimized
                new SerializableNoOp(),  // no override for methods mapped to this
                targetDispatcher, this.advisedDispatcher,
                new EqualsInterceptor(this.advised), 
                new HashCodeInterceptor(this.advised)
        };

        Callback[] callbacks;

        // If the target is a static one and the advice chain is frozen,
        // then we can make some optimizations by sending the AOP calls
        // direct to the target using the fixed chain for that method.
        // 下面是对方法对应哪些Callback作的一层优化,可以直接根据 fixedInterceptorMap 获取直接通过idx + offset 得到当前方法对应需要执行的Interceptor
        if (isStatic && isFrozen) {
            Method[] methods = rootClass.getMethods();
            Callback[] fixedCallbacks = new Callback[methods.length];
            this.fixedInterceptorMap = new HashMap<>(methods.length);

            // TODO: small memory optimization here (can skip creation for methods with no advice)
            for (int x = 0; x < methods.length; x++) {
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
                fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                        chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                this.fixedInterceptorMap.put(methods[x].toString(), x);
            }

            // Now copy both the callbacks from mainCallbacks
            // and fixedCallbacks into the callbacks array.
            callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
            System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
            System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
            this.fixedInterceptorOffset = mainCallbacks.length;
        }
        else {
            callbacks = mainCallbacks;
        }
        return callbacks;
    }
    //...
}

4、编程式创建spring aop对象

通过上面的了解,现在对spring aop的实现 有了更深的认识。
下面就基于spring编程式aop,来实现aop代理的创建。
public class SpringAopDemo {

    @Test
    public void demo1() throws Exception {

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setProxyTargetClass(false);
        proxyFactory.setFrozen(false);
        proxyFactory.setOpaque(false); //设置将aop配置透明化处理
        proxyFactory.setExposeProxy(true); //给被切入的方法暴露proxy对象
        proxyFactory.addAdvice(new MethodBeforeAdviceInterceptor(new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object target) throws Throwable {
                System.out.println("前置通知");
            }

        }) {
            @Override
            public String toString() {
                return "前置通知";
            }
        });
        proxyFactory.addAdvice(new AfterReturningAdviceInterceptor(new AfterReturningAdvice() {
            @Override
            public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
                System.out.println("正常返回通知");
            }

        }){
            @Override
            public String toString() {
                return "正常返回通知";
            }
        });
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("拦截环绕通知-前");
                Object retVal = invocation.proceed();
                System.out.println("拦截环绕通知-后");
                return retVal;
            }

            @Override
            public String toString() {
                return "环绕通知";
            }
        });
        proxyFactory.addAdvice(new ThrowsAdviceInterceptor(new ThrowingAdvice()){
            @Override
            public String toString() {
                return "异常通知";
            }
        });
        proxyFactory.setTarget(new TargetObject());
        Say proxy = (Say) proxyFactory.getProxy();
        proxy.doSay();

    }

    interface Say {
        void doSay();
    }

    class TargetObject implements Say {
        public void doSay() {
            Object currentProxy = AopContext.currentProxy();
            System.out.println("\t\t\t当前代理:" + currentProxy);
            Advised advised = (Advised) currentProxy;
            System.out.println("\t\t\t设置AOP配置透明化处理,AOP配置信息:" + Arrays.toString(advised.getAdvisors()));
            System.out.println("\t\t\tproxy class:" + currentProxy.getClass());
            System.out.println("\t\t\ttarget class:" + ((TargetClassAware) currentProxy).getTargetClass());

            System.out.println("hello word.");
            //throw new RuntimeException("异常了。。。");
        }
    }

    public class ThrowingAdvice {
        public void afterThrowing(Throwable t) {
            System.out.println("异常通知:" + t.getMessage());
        }
    }
}
控制台输出结果:
        前置通知
        拦截环绕通知-前
            ①前置通知
            ②拦截环绕通知-前
            ③拦截环绕通知-后
            ④正常返回通知
                    当前代理:com.example.lcc.basic.spring.aop.SpringAopDemo$TargetObject@1bce4f0a
                    设置AOP配置透明化处理,AOP配置信息:[org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [前置通知], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [正常返回通知], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [环绕通知], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [异常通知]]
                    proxy class:class com.example.lcc.basic.spring.aop.SpringAopDemo$TargetObject$$EnhancerBySpringCGLIB$$e8b223a8
                    target class:class com.example.lcc.basic.spring.aop.SpringAopDemo$TargetObject
        hello word.
        拦截环绕通知-后
        正常返回通知
 在查看控制台结果时会发现多出①②③④ 这四句看似不应该出现的输出,开始还以为是哪里出了问题,仔细分析了下代码才发现,
在这句:System.out.println("\t\t\t当前代理:" + currentProxy); 实际是调用了currentProxy.toString()方法
toString方法也是个代理方法,会引入方面的Advice因此①②③④ 其实是toString()触发的方面执行,
另外在debug时,如图:

这里写图片描述
会发现每走一步,控制台都会重复输出①②③④

前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
//...
 这是因为IDEA debug时会自动尝试获取对象的toString()输出展示到当前行的后面(注意图片中的灰体部分),
 又因为toString方法是被代理的方法,因此会产生看似不可思议的结果。

这个debug问题的stackoverflow链接地址

总结:
    spring aop属于一套spring风格的api,它是通过jdk动态代理、与cglib的动态代理来实现的这套api,而且对于由spring bean容器管理的对象,使用aop会非常的
    方便,但是如果想对那些不是由spring容器管理的对象进行方面编程,就没办法了。如:对pojo的方面编程,那样就需要通过其他aop框架来实现了,如aspectj。
    使用spring aop对比aspectj的好处就是无需在开发和构建过程中 引入专用的compiler/weaver,坏处就是spring aop局限于要将对象交给它来管理才能使用。 

猜你喜欢

转载自blog.csdn.net/m0_38043362/article/details/80388698