网站建设优化重庆,佛山网站建设设计,企业查查天眼查询,如何做印刷报价网站Spring Aop
看这个分享的应该都用过Spring Aop#xff0c;这里就不再过多介绍了它是什么了。
我抽取了Spring Aop的部分源码#xff0c;通过它实现请求参数可变拦截#xff0c;同时apisdk离开Spring框架#xff0c;仍然可以正常运行。
讲拦截也好#xff0c;通知也罢这里就不再过多介绍了它是什么了。
我抽取了Spring Aop的部分源码通过它实现请求参数可变拦截同时apisdk离开Spring框架仍然可以正常运行。
讲拦截也好通知也罢大家知道是什么意思就行了不需要纠结这个叫法。
核心拓展类
利用Aop的前置通知拓展了前置参数可变通知原理是在运行的过程中动态封装请求上下文SdkContext参数变更请求参数。 上面圈的类是参照Aop的代码结构拓展出的通知描述如下
MethodBeforeArgsChangeableAdvice需要开发者实现的接口在apisdk中唯一实现SdkContextArgsBeforeChangeableAdvice实现了SdkContext的构建MethodBeforeChangeableAdviceAdapter适配器把开发者实现的MethodBeforeArgsChangeableAdvice交给底层去执行是框架执行开发者代码的入口MethodBeforeChangeableAdviceInterceptor执行开发者的MethodBeforeArgsChangeableAdvice最后把结果添加到方法参数上SdkContextArgsBeforeChangeableAdviceMethodBeforeArgsChangeableAdvice的唯一实现实现了SdkContext的关键代码
核心代码
SdkContext自动封装
public class SdkContextArgsBeforeChangeableAdvice implements MethodBeforeArgsChangeableAdvice {Overridepublic Object before(Method method, Object[] args, Object target) throws Throwable {// 判断执行的方法是否需要自动注入 SdkContext// 如果用户的接口声明的方法参数有 SdkContext则说明用户要手动创建否则底层自动创建boolean isAutoType MethodWrapperCache.isAutoType(method);if (isAutoType) {// SdkContextManager 封装了域名、secret、token等服务的调用SdkContextManager instance SdkContextManager.getInstance();SdkContext sdkContext instance.getSdkContext();return sdkContext;}return null;}
}动态调整请求参数
MethodBeforeChangeableAdviceInterceptor
public class MethodBeforeChangeableAdviceInterceptor implements MethodInterceptor, BeforeAdvice {private MethodBeforeArgsChangeableAdvice advice;public MethodBeforeChangeableAdviceInterceptor(MethodBeforeArgsChangeableAdvice advice) {this.advice advice;}Overridepublic Object invoke(MethodInvocation mi) throws Throwable {// 调用开发者的 MethodBeforeArgsChangeableAdviceObject arg this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());if (arg ! null mi instanceof ReflectiveMethodInvocation) {// 将 MethodBeforeArgsChangeableAdvice 返回的结果添加到调用方法((ReflectiveMethodInvocation) mi).appendArgument(arg);}return mi.proceed();}
}ReflectiveMethodInvocation#appendArgument
public class ReflectiveMethodInvocation implements MethodInvocation {// 方法参数protected Object[] arguments;// 调整方法请求参数public void appendArgument(Object obj) {if (this.arguments ! null this.arguments.length 0) {int length this.arguments.length;Object[] newArgs new Object[length 1];System.arraycopy(this.arguments, 0, newArgs, 0, length);newArgs[length] obj;this.arguments newArgs;} else {this.arguments new Object[1];this.arguments[0] obj;}}
}Jdk 动态代理
原始接口A和增强接口B他们的实例化必须由动态代理支持。apisdk有SdkManager和JdkDynamicAopProxy两个代理对象生成器SdkManager是原代码中就有的JdkDynamicAopProxy是我参考Spring aop拓展的。
二开后SdkManager用于生成B的代理对象JdkDynamicAopProxy用于生成A的代理对象并且配置了一系列的拦截动作。
开发逻辑开发者使用A的代理对象调用方法底层执行A方法执行拦截动作再拿到B的代理对象执行B的方法。
JdkDynamicAopProxy代码如下
public class JdkDynamicAopProxy implements InvocationHandler {// 包装被代理的对象每个被代理的对象都有一组Adviceprivate AdvisedSupport advised;public JdkDynamicAopProxy(AdvisedSupport advised) {this.advised advised;}public Object getProxy() {return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), advised.getProxiedInterfaces(), this);}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 获取被代理的对象Object target advised.getTarget();// 获取 Method 匹配的所有 AdviceListObject chain this.advised.getInterceptors(method, target.getClass());Object retVal;if (chain.isEmpty()) {// 没有 Advice直接执行 MethodretVal method.invoke(target, args);} else {// 递归调用 AdviceReflectiveMethodInvocation reflectiveMethodInvocation new ReflectiveMethodInvocation(proxy, target, method, args, chain);retVal reflectiveMethodInvocation.proceed();}return retVal;}
}