spring Aop通知调用链源码分析 (1-4)

Aop通知调用链源码分析

责任链模式

public interface GatewayHandler {
    /**
     * Boolean返回类型的作用是干嘛? 使用递归停止下一步
     */
    public Boolean service();
}
public class BlacklistHandler implements GatewayHandler {
    public Boolean service() {
        System.out.println(">>>第二关 黑名单拦截");
        return true;
    }
}
public class CurrentLimitHandler implements GatewayHandler {
    public Boolean service() {
        System.out.println("第一关>>>api接口的限流");
        return true;
    }
}

核心实现

public class GatewayHandlerUtils {
    private List<GatewayHandler> listGatewayHandler;
    private int index;

    public GatewayHandlerUtils() {
        listGatewayHandler = new ArrayList<GatewayHandler>();
        listGatewayHandler.add(new CurrentLimitHandler());
        listGatewayHandler.add(new BlacklistHandler());
    }

    public void invoke() {
        for (int i = 0; i < listGatewayHandler.size(); i++) {
            GatewayHandler gatewayHandler = listGatewayHandler.get(i);
            Boolean service = gatewayHandler.service();
            if (!service) {
                return;
            }
        }
    }

    public void recurrenceInvoke() {
        // 大数据批量拆分  百万级消息群发 每次只发送一万条
        if (index == listGatewayHandler.size()) {
            return;
        }
        GatewayHandler gatewayHandler = listGatewayHandler.get(index++);
        Boolean service = gatewayHandler.service();
        if (!service) {
            return;
        }
        recurrenceInvoke();
    }
}

测试

public class Test {
    public static void main(String[] args) {
        GatewayHandlerUtils gatewayHandlerUtils = new GatewayHandlerUtils();
        gatewayHandlerUtils.recurrenceInvoke();
    }
}

aop 中使用责任链执行通知

  1. 注入 AnnotationAwareAspectJAutoProxyCreator–>AbstractAutoProxyCreator–> postProcessAfterInitialization (方法) --> wrapIfNecessary (方法) --> JdkDynamicAopProxy
  2. 执行时调用 invoke 方法
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();
}

proceed() 方法

public Object proceed() throws Throwable {
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return this.invokeJoinpoint();
	} else {
		Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
			return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
		} else {
			return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
		}
	}
}

手动实现 aop 责任链

定义 Interceptor

public interface MethodInterceptor {
    /**
     * 定义共同通知骨架
     */
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException;
}

public class BeforMethodInterceptor implements MethodInterceptor {
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        System.out.println(">>>>前置通知<<<<");
        // 执行我们的目标方法
        methodInvocation.process();// 递归调用
    }
}

public class AroundMethodInterceptor implements MethodInterceptor {
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        System.out.println("环绕通知在目标方法之前执行..");
        methodInvocation.process();
        System.out.println("环绕通知在目标方法之后执行..");
    }
}
public class AfterMethodInterceptor implements MethodInterceptor {
    public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        // 执行我们的前置通知
        methodInvocation.process();
        System.out.println(">>>后置通知<<<");
    }
}

定义 Invocation

public interface MethodInvocation {
	// 能够把通知链形成关联
    public void process() throws InvocationTargetException, IllegalAccessException;
}

public class DefaultMethodInvacation implements MethodInvocation {
    /**
     * 存放所有的通知
     */
    private List<MethodInterceptor> listMethodInterceptor;
    private Object target;// 目标对象
    private Method method;// 目标方法
    private Object args[];// 目标参数
    // 最终使用反射机制执行目标方法
    private int index;// 记录当前链调用的位置

    public DefaultMethodInvacation(List<MethodInterceptor> listMethodInterceptor, Object target, Method method, Object[] args) {
        this.listMethodInterceptor = listMethodInterceptor;
        this.target = target;
        this.method = method;
        this.args = args;
    }

    public DefaultMethodInvacation(List<MethodInterceptor> listMethodInterceptor) {
        this.listMethodInterceptor = listMethodInterceptor;
    }

    /**
     * 调用链形成
     */
    public void process() throws InvocationTargetException, IllegalAccessException {
        if (index == listMethodInterceptor.size()) {//做了一个指针,很妙
            method.invoke(target, args); //  执行目标
            return;
        }
        MethodInterceptor methodInterceptor = listMethodInterceptor.get(index++);
        methodInterceptor.invoke(this);
    }
}

核心业务 service

public class UserService {
    public void login(String userName, Integer age) {
        System.out.println("userName:" + userName + ",age:" + age);
    }
}

调用测试

public class Test00 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 1.装配所有的通知存放到集合中
        ArrayList<MethodInterceptor> methodInterceptors = new ArrayList<MethodInterceptor>();
        methodInterceptors.add(new BeforMethodInterceptor());
        methodInterceptors.add(new AfterMethodInterceptor());
        methodInterceptors.add(new AroundMethodInterceptor());
//        new MethodInvocation(methodInterceptors).process();
        // 2.创建我们的目标方法
        UserService userService = new UserService();
        Method loginMethod = UserService.class.getMethod("login", String.class, Integer.class);
        Object[] objects = {"mayikt", 12};
        new DefaultMethodInvacation(methodInterceptors, userService, loginMethod, objects).process();
        // SpringAop底层 所有的通知最终使用递归算法调用+责任链设计模式
        // 第一关 APi接口限流 第二关 黑名单拦截
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值