mini-Spring 代理篇-AOP:Step 15:补全aop的其他方法,完善可排序的拦截器链

这章的原标题“给代理对象的属性设置值”,就是把创建代理对象的步骤从在整个创建 Bean 对象之前(不算在 Bean 生命周期中)融入到 Bean 的生命周期中,也就是需要把创建代理对象的逻辑迁移到 Bean 对象执行初始化方法之后,在执行代理对象的创建。但是我已经提前完成了…
mini-Spring 代理篇-AOP:Step 12:将 AOP 动态代理融入 Bean 生命周期 – CMD137’s Blog之“大的要来了!开始大修”。

那么这一章就来补全aop的其他方法(after、around),完善可排序的拦截器链。系统性的梳理一下整个aop系统。

0.做点小优化:

TargetSource

public Class<?> getTargetClass() {
        // 返回原始类类型,而不是接口
        // 如果目标是代理类(比如 CGLIB 生成的),也能返回其父类
        Class<?> clazz = this.target.getClass();
        // 防止 CGLIB 子类导致的接口丢失问题
        if (clazz.getName().contains("$$")) {
            return clazz.getSuperclass();
        }
        return clazz;
    }

原来的.contains(“$$”)不够优雅,所以:

public Class<?> getTargetClass() {
Class<?> clazz = this.target.getClass();
clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
return clazz;
}

(虽然工具类内部也是.contains(“$$”)…)



1.补充after、around:

1.1 after:

1.1.1 AfterAdvice:

/**
 * 后置通知标记接口,在目标方法执行后调用的增强类型。
 */
public interface AfterAdvice extends Advice {
}

1.1.2 MethodAfterAdvice

import java.lang.reflect.Method;

/**
 * 方法执行后的回调通知。
 * 在目标方法调用后执行,可用于日志记录、清理资源等操作。
 */
public interface MethodAfterAdvice extends AfterAdvice {

    /**
     * 目标方法执行后调用
     */
    void after(Method method, Object[] args, Object target, Object returnValue) throws Throwable;
}

1.1.3 MethodAfterAdviceInterceptor:

/**
 * MethodAfterAdviceInterceptor 是后置通知(After Advice)到方法拦截器(MethodInterceptor)的适配器。
 *
 * 它将具体的 MethodAfterAdvice 转换成 MethodInterceptor 接口,
 * 使得后置通知能够参与统一的拦截器链调用流程。
 *
 * 作用:
 * - 解耦通知接口和拦截器接口,方便将不同类型的通知统一管理和执行。
 * - 让后置通知可以像环绕通知一样参与方法调用的拦截器链,实现链式调用。
 */
public class MethodAfterAdviceInterceptor implements MethodInterceptor {

    /**
     * 持有具体的后置通知实现
     */
    private MethodAfterAdvice advice;
    
    // 添加无参构造函数,用于实例化(关键)
    public MethodAfterAdviceInterceptor() {
    }

    public MethodAfterAdviceInterceptor(MethodAfterAdvice advice) {
        this.advice = advice;
    }

    /**
     * 拦截方法调用,先执行目标方法,然后执行后置通知
     *
     * @param methodInvocation 当前方法调用的封装,包含目标对象、方法、参数和拦截器链
     */
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        // 执行调用链,最终执行目标方法
        Object returnValue = methodInvocation.proceed();
        // 调用后置通知
        advice.after(methodInvocation.getMethod(), methodInvocation.getArguments(),
                     methodInvocation.getThis(), returnValue);
        return returnValue;
    }
}

1.2 Around:

1.2.1 AroundAdvice

/**
 * 环绕通知标记接口。
 * 环绕通知可以在目标方法执行前后都进行增强操作,
 * 并且可以控制是否执行目标方法。
 */
public interface AroundAdvice extends Advice {
}

1.2.2 MethodAroundAdvice

import java.lang.reflect.Method;

/**
 * 方法执行前后都可增强的回调通知。
 * 环绕通知可以决定是否执行目标方法,并可在执行前后添加自定义逻辑。
 */
public interface MethodAroundAdvice extends AroundAdvice {

    /**
     * 环绕通知方法
     */
    Object around(Method method, Object[] args, Object target, MethodInvocation invocationMethodChain) throws Throwable;
}

这里 MethodInvocation 可以让环绕通知控制是否调用目标方法,或者在调用前后做逻辑。


1.2.3 MethodAroundAdviceInterceptor

/**
 * MethodAroundAdviceInterceptor 是环绕通知到方法拦截器的适配器。
 *
 * 它将具体的 MethodAroundAdvice 转换成 MethodInterceptor 接口,
 * 使环绕通知可以参与统一的拦截器链调用流程。
 */
public class MethodAroundAdviceInterceptor implements MethodInterceptor {

    private MethodAroundAdvice advice;
    
    // 添加无参构造函数,用于实例化(关键)
    public MethodAroundAdviceInterceptor() {
    }

    public MethodAroundAdviceInterceptor(MethodAroundAdvice advice) {
        this.advice = advice;
    }

    /**
     * 拦截方法调用,将环绕通知委托给 MethodAroundAdvice
     */
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        return advice.around(
            methodInvocation.getMethod(),
            methodInvocation.getArguments(),
            methodInvocation.getThis(),
            methodInvocation
        );
    }
}

注意:around与其他两个相比,特殊在环绕通知内部自己决定什么时候调用 invocation.proceed(),甚至可以完全不调用,从而阻止方法执行或替换返回值。
所以要在具体实现方法中主动/调用目标方法或下一个拦截器:
Object returnValue = invocation.proceed();

1.3 测试

三个拦截方法:

public class LogBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知: 方法 " + method.getName() + " 即将执行");
}
}
public class LogAfterAdvice implements MethodAfterAdvice {
    @Override
    public void after(Method method, Object[] args, Object target, Object returnValue) throws Throwable {
        System.out.println("后置通知: 方法 " + method.getName() + " 执行完毕, 返回值: " + returnValue);
    }
}
public class LogAroundAdvice implements MethodAroundAdvice {
    @Override
    public Object around(Method method, Object[] args, Object target, MethodInvocation invocation) throws Throwable {
        System.out.println("环绕通知: 方法 " + method.getName() + " 执行前");
        Object returnValue = invocation.proceed(); // 执行目标方法或下一个拦截器
        System.out.println("环绕通知: 方法 " + method.getName() + " 执行后, 返回值: " + returnValue);
        return returnValue;
    }
}

xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean class="com.miniSpring.beans.factory.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:token.properties"/>
    </bean>

    <!-- 自动代理创建器:-->
    <bean class="com.miniSpring.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

    <!-- aop组合1-->
    <bean id="beforeAdvice1" class="com.miniSpring.test.bean.LogBeforeAdvice"/>

    <bean id="methodInterceptor1" class="com.miniSpring.aop.adapter.MethodBeforeAdviceInterceptor">
        <property name="advice" ref="beforeAdvice1"/>
    </bean>

    <bean id="pointcutAdvisor1" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor1"/>
    </bean>

    <!-- aop组合2-->
    <bean id="afterAdvice2" class="com.miniSpring.test.bean.LogAfterAdvice"/>

    <bean id="methodInterceptor2" class="com.miniSpring.aop.adapter.MethodAfterAdviceInterceptor">
        <property name="advice" ref="afterAdvice2"/>
    </bean>

    <bean id="pointcutAdvisor2" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor2"/>
    </bean>

    <!-- aop组合3-->
    <bean id="beforeAdvice3" class="com.miniSpring.test.bean.LogAroundAdvice"/>

    <bean id="methodInterceptor3" class="com.miniSpring.aop.adapter.MethodAroundAdviceInterceptor">
        <property name="advice" ref="beforeAdvice3"/>
    </bean>

    <bean id="pointcutAdvisor3" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor3"/>
    </bean>


    <component-scan base-package="com.miniSpring.test.bean"/>
</beans>

单元测试:

@Test
public void test() {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
    IUserService userService = applicationContext.getBean("userService", IUserService.class);
    System.out.println("测试结果:" + userService.queryUserInfo());
}

测试结果:

前置通知: 方法 queryUserInfo 即将执行
环绕通知: 方法 queryUserInfo 执行前
环绕通知: 方法 queryUserInfo 执行后, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
后置通知: 方法 queryUserInfo 执行完毕, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
测试结果:CMD137,北京,亦庄,123_TEST_TOKEN_321

可以看到aop都实现了,那么问题来了。顺序怎么决定的。这里由于都是注册为bean,放在hashmap里,所以执行的顺序是不可掌握的,所以接下来就让我们实现可确定顺序的aop链。

2.实现切面排序机制:

2.1 借鉴真实 Spring 的 AOP 设计思路

在真实的 Spring 框架中,AOP 并不是简单地直接执行 Advice(通知方法),而是通过**一条拦截器链(Interceptor Chain)**来完成的。
执行流程大致如下:

  1. 收集所有符合当前方法的 Advisor(切面定义)
  2. 将 Advisor 转换为 MethodInterceptor(方法拦截器)
  3. 按照 order 顺序对拦截器链排序
  4. 依次执行拦截器,最终调用目标方法

Spring 里的关键角色:

  • Advisor:切面定义,包含 Pointcut(切入点)+ Advice(通知逻辑)
  • Advice:通知逻辑,比如 Before、After、Around
  • MethodInterceptor:统一的执行接口,拦截调用并执行增强逻辑
  • AdvisorAdapterRegistry:适配器注册中心,把不同类型的 Advice 适配成 MethodInterceptor

我们 miniSpring 也沿用了这个思路,只是做了简化,把 AdvisorAdapterRegistry 逻辑直接放在了 DefaultAdvisorAutoProxyCreator 里进行“逻辑适配”。、


2.1 为什么要用适配器模式?

在 AOP 中,有多种类型的 Advice:

  • MethodBeforeAdvice(前置通知)
  • MethodAfterAdvice(后置通知)
  • MethodAroundAdvice(环绕通知)

如果我们让代理类直接依赖这些接口,就会出现一个问题:

代理类必须写很多 if/else 来区分 Advice 类型,代码耦合度高,不好扩展。

Spring 的做法是——适配器模式

  • 为每种 Advice 提供一个适配器,比如:
    • MethodBeforeAdviceInterceptor
  • 这些适配器统一实现 MethodInterceptor 接口
  • 代理类只需要和 MethodInterceptor 打交道,不关心底层是 before 还是 after

miniSpring 的适配器类示例:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor {

    private final MethodBeforeAdvice advice;

    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        advice.before(invocation.getMethod(), invocation.getArguments(), invocation.getThis());
        return invocation.proceed();
    }
}

具体来说,适配器MethodBeforeAdviceInterceptor 让适配者MethodBeforeAdvice 实现了MethodInterceptor 接口,从而可以调用invoke方法


2.3 Advisor 的顺序排序机制

一个常见的 AOP 场景是:

先执行一个日志切面,再执行一个事务切面。

如果没有顺序控制,切面的执行顺序就会变得不可预测。
Spring 通过 org.springframework.core.Ordered 接口来解决这一问题:

public interface Ordered {
    int getOrder();
}

在 miniSpring 中,我们同样让 AspectJExpressionPointcutAdvisor 实现一个 Ordered 接口:

public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor, Ordered {

    private String expression;
    private Advice advice;
    private int order = Integer.MAX_VALUE; // 默认优先级最低

    @Override
    public int getOrder() {
        return this.order;
    }

    public void setOrder(int order) {
        this.order = order;
    }
}

真实spring在AbstractAdvisorAutoProxyCreator中对advisor进行了排序。

这里我们选择在具体代理类中从AdvisedSupport中获得advisor数组后在排序,并进行适配,见下:

2.4 具体排序实现与扩展更多通知类型:

这里需要修改一下advise的存储类型,之前写为PointcutAdvisor,为了支持排序,应该为AspectJExpressionPointcutAdvisor

package com.miniSpring.aop;

import com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor;

import java.util.ArrayList;
import java.util.List;

/**
 * AdvisedSupport 是 AOP 代理配置的核心承载类,
 * 用于保存目标对象、方法拦截器链和方法匹配器等信息。
 *
 * 主要职责:
 *  - 保存被代理的目标对象(TargetSource)
 *  - 保存方法拦截器链(List<MethodInterceptor>)
 *  - 保存方法匹配器(MethodMatcher),用于判断是否应用拦截器
 *
 * 这样设计方便代理生成时统一读取相关配置,
 * 并支持多拦截器的链式调用,增强灵活性。
 */
public class AdvisedSupport {

    /**
     * 封装目标对象及其类型
     */
    private TargetSource targetSource;

    // 改成存 Advisor 列表,而非 MethodInterceptor 列表
    private List<AspectJExpressionPointcutAdvisor> advisors = new ArrayList<AspectJExpressionPointcutAdvisor>();

    /**
     * 方法匹配器,判断某个方法是否需要被增强
     */
    private MethodMatcher methodMatcher;

    /*
    默认false代表用JDK动态代理,true代表用Cglib。
     */
    private boolean proxyTargetClass = false;

    public boolean isProxyTargetClass() {
        return proxyTargetClass;
    }

    public void setProxyTargetClass(boolean proxyTargetClass) {
        this.proxyTargetClass = proxyTargetClass;
    }


    // ========== getter/setter ==========

    public TargetSource getTargetSource() {
        return targetSource;
    }



    public void setTargetSource(TargetSource targetSource) {
        this.targetSource = targetSource;
    }

    public List<AspectJExpressionPointcutAdvisor> getAdvisors() {
        return advisors;
    }

    public void setAdvisors(List<AspectJExpressionPointcutAdvisor> advisors) {
        this.advisors = advisors;
    }

    public MethodMatcher getMethodMatcher() {
        return methodMatcher;
    }

    public void setMethodMatcher(MethodMatcher methodMatcher) {
        this.methodMatcher = methodMatcher;
    }

    // ========== 方便添加单个拦截器的辅助方法 ==========

    /**
     * 方便向拦截器链添加一个advisor
     */
    public void addAdvisor(AspectJExpressionPointcutAdvisor advisor) {
        this.advisors.add(advisor);
    }
}

JdkDynamicAopProxy:

/**
 * 基于 JDK 动态代理的 AOP 代理实现类。
 * 通过实现 InvocationHandler 接口,实现对目标对象方法的拦截和增强。
 */
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {

    /**
     * 封装了被代理对象、方法匹配器和方法拦截器等信息的配置类
     */
    private final AdvisedSupport advisedSupport;

    /**
     * 构造函数,传入被代理的配置信息
     * @param advised 代理相关的配置,包括目标对象、方法匹配器、拦截器等
     */
    public JdkDynamicAopProxy(AdvisedSupport advised) {
        this.advisedSupport = advised;
    }

    /**
     * 创建并返回目标对象的 JDK 动态代理对象
     * @return 代理对象,类型为目标对象的接口类型
     */
    @Override
    public Object getProxy() {
        // 使用当前线程上下文类加载器,目标类接口列表,以及当前对象(作为 InvocationHandler)
        // 1. 获取目标对象的Class(如UserService.class)
        Class<?> targetClass = advisedSupport.getTargetSource().getTargetClass();

        //debug:
        //System.out.println("目标类:" + targetClass.getName());

        // 2. 获取目标对象实现的所有接口(关键:必须是接口数组)
        Class<?>[] interfaces = targetClass.getInterfaces();

        // 3. 验证是否有接口(JDK代理必须基于接口)
        if (interfaces.length == 0) {
            throw new BeansException("目标类 " + targetClass.getName() + " 未实现任何接口,无法使用JDK动态代理");
        }

        //debug:
//        for (Class<?> iface : interfaces) {
//            //System.out.println("代理实现的接口:" + iface.getName());
//            // 应输出:com.miniSpring.test.bean.IUserService
//        }


        // 4. 传入接口数组创建代理
        return Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                interfaces, // 正确:传入接口数组(如[IUserService.class])
                this
        );
    }

    /**
     * 代理对象的方法调用处理逻辑,实现了方法拦截增强功能
     * @param proxy 代理对象本身(一般不直接使用)
     * @param method 被调用的方法
     * @param args 方法参数
     * @return 方法调用结果
     * @throws Throwable 方法执行过程中抛出的异常
     */

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 1. 检查是否是Object类的方法(如toString、hashCode等),这些方法通常不需要增强
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(advisedSupport.getTargetSource().getTarget(), args);
        }


        // 2. 获取匹配的Advisor
        List<AspectJExpressionPointcutAdvisor> eligibleAdvisors = new ArrayList<>();
        for (AspectJExpressionPointcutAdvisor advisor : advisedSupport.getAdvisors()) {
            if (advisor.getPointcut().getMethodMatcher()
                    .matches(method, advisedSupport.getTargetSource().getTarget().getClass())) {
                eligibleAdvisors.add(advisor);
            }
        }

        // 3. 对 Advisors 按 Order 排序
        eligibleAdvisors.sort(Comparator.comparingInt(Ordered::getOrder));


        // 4. 转换 Advisors → MethodInterceptors(使用适配器注册中心)
        List<MethodInterceptor> interceptorChain = new ArrayList<>();
        for (Advisor advisor : eligibleAdvisors) {
            interceptorChain.addAll(adaptAdviceToInterceptor(advisor.getAdvice()));
        }

        // 4. 创建方法调用器,封装目标对象、方法、参数和拦截器链
        ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(
                advisedSupport.getTargetSource().getTarget(),
                method,
                args,
                interceptorChain
        );

        // 5. 执行拦截器链(责任链模式),最终调用目标方法
        return invocation.proceed();

    }

    /**
     * 把 Advice 转换成 MethodInterceptor 列表
     * 模拟 Spring 的 AdvisorAdapterRegistry
     */
    private List<MethodInterceptor> adaptAdviceToInterceptor(Advice advice) {
        List<MethodInterceptor> interceptors = new ArrayList<>();

        if (advice instanceof MethodAroundAdvice) {
            interceptors.add(new MethodAroundAdviceInterceptor((MethodAroundAdvice) advice));
        } else if (advice instanceof MethodBeforeAdvice) {
            interceptors.add(new MethodBeforeAdviceInterceptor((MethodBeforeAdvice) advice));
        } else if (advice instanceof MethodAfterAdvice) {
            interceptors.add(new MethodAfterAdviceInterceptor((MethodAfterAdvice) advice));
        } else if (advice instanceof MethodInterceptor) {
            // 仅对已经实现了 MethodInterceptor 的 Advice 支持直接加入
            interceptors.add((MethodInterceptor) advice);
        } else {
            throw new IllegalArgumentException("Unsupported advice type: " + advice.getClass());
        }

        return interceptors;
    }


}

Cglib2AopProxy:

public class Cglib2AopProxy implements AopProxy {

    private final AdvisedSupport advised;

    public Cglib2AopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }

    @Override
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(advised.getTargetSource().getTarget().getClass());
        enhancer.setInterfaces(advised.getTargetSource().getTargetInterfaces());
        // 传入当前 Cglib2AopProxy 实例,供内部类调用 adaptAdviceToInterceptor
        enhancer.setCallback(new DynamicAdvisedInterceptor(advised, this));
        return enhancer.create();
    }

    /**
     * 将 Advice 转换成 MethodInterceptor 列表
     */
    public List<org.aopalliance.intercept.MethodInterceptor> adaptAdviceToInterceptor(Advice advice) {
        List<org.aopalliance.intercept.MethodInterceptor> interceptors = new ArrayList<>();

        if (advice instanceof MethodAroundAdvice) {
            interceptors.add(new MethodAroundAdviceInterceptor((MethodAroundAdvice) advice));
        } else if (advice instanceof MethodBeforeAdvice) {
            interceptors.add(new MethodBeforeAdviceInterceptor((MethodBeforeAdvice) advice));
        } else if (advice instanceof MethodAfterAdvice) {
            interceptors.add(new MethodAfterAdviceInterceptor((MethodAfterAdvice) advice));
        } else if (advice instanceof org.aopalliance.intercept.MethodInterceptor) {
            interceptors.add((org.aopalliance.intercept.MethodInterceptor) advice);
        } else {
            throw new IllegalArgumentException("Unsupported advice type: " + advice.getClass());
        }

        return interceptors;
    }

    /**
     * CGLIB 的 MethodInterceptor
     * 负责拦截目标对象的方法调用,执行拦截器链或直接调用目标方法
     */
    private static class DynamicAdvisedInterceptor implements MethodInterceptor {

        private final AdvisedSupport advised;
        private final Cglib2AopProxy proxyInstance;

        public DynamicAdvisedInterceptor(AdvisedSupport advised, Cglib2AopProxy proxyInstance) {
            this.advised = advised;
            this.proxyInstance = proxyInstance;
        }

        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            // 1. Object 类方法直接调用,不做增强
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(advised.getTargetSource().getTarget(), args);
            }

            // 2. 获取匹配的 Advisor
            List<PointcutAdvisor> eligibleAdvisors = new ArrayList<>();
            for (PointcutAdvisor advisor : advised.getAdvisors()) {
                if (advisor.getPointcut().getMethodMatcher()
                        .matches(method, advised.getTargetSource().getTarget().getClass())) {
                    eligibleAdvisors.add(advisor);
                }
            }

            // 3. 对 Advisors 按 Order 排序
            eligibleAdvisors.sort(Comparator.comparingInt(advisor -> ((Ordered) advisor).getOrder()));


            // 4. 转换 Advisors → MethodInterceptors(通过外部 proxyInstance 调用)
            List<org.aopalliance.intercept.MethodInterceptor> interceptorChain = new ArrayList<>();
            for (Advisor advisor : eligibleAdvisors) {
                interceptorChain.addAll(proxyInstance.adaptAdviceToInterceptor(advisor.getAdvice()));
            }

            // 5. 执行拦截器链,传入自定义 CglibMethodInvocation
            CglibMethodInvocation invocation = new CglibMethodInvocation(
                    advised.getTargetSource().getTarget(),
                    method,
                    args,
                    methodProxy,
                    interceptorChain
            );
            return invocation.proceed();
        }
    }

    /**
     * CglibMethodInvocation 继承 ReflectiveMethodInvocation,复用拦截器链调用逻辑,
     * 并重写 proceed() 用 CGLIB 的 methodProxy 调用目标方法
     */
    private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

        private final MethodProxy methodProxy;

        public CglibMethodInvocation(Object target, Method method, Object[] arguments,
                                     MethodProxy methodProxy, List<org.aopalliance.intercept.MethodInterceptor> interceptors) {
            super(target, method, arguments, interceptors);
            this.methodProxy = methodProxy;
        }

        @Override
        public Object proceed() throws Throwable {
            if (currentInterceptorIndex == methodInterceptorList.size() - 1) {
                return methodProxy.invoke(target, arguments);
            }
            currentInterceptorIndex++;
            org.aopalliance.intercept.MethodInterceptor interceptor = methodInterceptorList.get(currentInterceptorIndex);
            return interceptor.invoke(this);
        }
    }
}

测试:

xml:

可以看到给每个AspectJExpressionPointcutAdvisor加上了order属性。

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean class="com.miniSpring.beans.factory.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:token.properties"/>
    </bean>

    <!-- 自动代理创建器:-->
    <bean class="com.miniSpring.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

    <!-- aop组合1-->
    <bean id="beforeAdvice1" class="com.miniSpring.test.bean.LogBeforeAdvice"/>

    <bean id="methodInterceptor1" class="com.miniSpring.aop.adapter.MethodBeforeAdviceInterceptor">
        <property name="advice" ref="beforeAdvice1"/>
    </bean>

    <bean id="pointcutAdvisor1" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor1"/>
        <property name="order" value="3"/>
    </bean>

    <!-- aop组合2-->
    <bean id="afterAdvice2" class="com.miniSpring.test.bean.LogAfterAdvice"/>

    <bean id="methodInterceptor2" class="com.miniSpring.aop.adapter.MethodAfterAdviceInterceptor">
        <property name="advice" ref="afterAdvice2"/>
    </bean>

    <bean id="pointcutAdvisor2" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor2"/>
        <property name="order" value="2"/>
    </bean>

    <!-- aop组合3-->
    <bean id="aroundAdvice3" class="com.miniSpring.test.bean.LogAroundAdvice"/>

    <bean id="methodInterceptor3" class="com.miniSpring.aop.adapter.MethodAroundAdviceInterceptor">
        <property name="advice" ref="aroundAdvice3"/>
    </bean>

    <bean id="pointcutAdvisor3" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor3"/>
        <property name="order" value="1"/>
    </bean>


    <component-scan base-package="com.miniSpring.test.bean"/>
</beans>

结果:

其他都不变,得到结果:

可以看到环绕通知先执行了,与明确排序的一样,而之前是前置通知先执行。

环绕通知: 方法 queryUserInfo 执行前
前置通知: 方法 queryUserInfo 即将执行
后置通知: 方法 queryUserInfo 执行完毕, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
环绕通知: 方法 queryUserInfo 执行后, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
测试结果:CMD137,北京,亦庄,123_TEST_TOKEN_321

Process finished with exit code 0

简单梳理整个aop系统:

实现一个aop具体组合:

1.创建一个AspectJExpressionPointcutAdvisor Bean, AspectJExpressionPointcutAdvisor内:
1.1 expression String:切入点表达式
1.2 advice MethodBeforeAdviceInterceptor(2.)(实现MethodInterceptor,MethodInterceptor实现advice): 具体的拦截方法实现。
1.3 order int:拦截链排序。

2.创建一个MethodBeforeAdviceInterceptor Bean:
2.1 advice 自定义方法,继承MethodBeforeAdvice/MethodAfterAdvice

3.自定义拦截方法,需要实现相对应的接口:

  • MethodBeforeAdvice
  • MethodAfterAdvice
  • MethodAroundAdvice

aop生命周期:

在目标类bean的初始化完成后,DefaultAdvisorAutoProxyCreator 检查所有 Advisor(因为实现了postProcessAfterInitialization),如果有匹配的AspectJExpressionPointcutAdvisor,就会开启代理流程:

1.打包所有通过 Pointcut 匹配筛选出适用于当前 bean 的 Advisor通知器到advisedSupport中。
2.使用代理工厂开始创建代理对象:
3.在invoke方法中从advisedSupport中得到所有的Advisor,并按照order排序。
4.转换 Advisors → MethodInterceptors(使用适配器注册中心)
5.创建方法调用器ReflectiveMethodInvocation,封装目标对象、方法、参数和拦截器链,让代理类存储对原始方法的引用以及AdvisedSupport对象,这个代理逻辑的 “元数据容器”。
6.返回被代理的对象。
7.调用目标方法 invoke () :
7.1:代理对象会创建一个ReflectiveMethodInvocation对象,它封装了:
目标对象(原始对象)
要执行的方法(doSomething()
方法参数
拦截器链(包含BeforeAdviceAfterAdvice对应的拦截器)
7.2 : 直接调用这个ReflectiveMethodInvocation对象的proceed()方法启动整个执行流程。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇