0. 下了有一个月的雨,这对鼻炎来说来吗?不好

其实这也算6月份的博客,之前一直疏于整理


  • 本文仅关注jdk代理所实现的spring.aop下,两者的关系
  • 完整的aop源码走读请移步相关 spring.aop 的其他随笔

1. 反编译追踪源码

1.1 jdk代理类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//import com.weng.cloud.sample.aop.dto.Order;
import com.weng.cloud.sample.aop.service.OrderService;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements OrderService, Serializable {private static Method m1;private static Method m4;private static Method m3;private static Method m2;private static Method m0;public $Proxy0(InvocationHandler var1) throws  {super(var1);}public final boolean equals(Object var1) throws  {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}// 接口实现类public final Order queryOrder(String var1) throws  {try {// step into super class(invocationHandler) ...return (Order)super.h.invoke(this, m4, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}// 接口实现类public final Order createOrder(String var1, String var2) throws  {try {return (Order)super.h.invoke(this, m3, new Object[]{var1, var2});} catch (RuntimeException | Error var4) {throw var4;} catch (Throwable var5) {throw new UndeclaredThrowableException(var5);}}public final String toString() throws  {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws  {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m4 = Class.forName("com.weng.cloud.sample.aop.service.OrderService").getMethod("queryOrder", Class.forName("java.lang.String"));m3 = Class.forName("com.weng.cloud.sample.aop.service.OrderService").getMethod("createOrder", Class.forName("java.lang.String"), Class.forName("java.lang.String"));m2 = Class.forName("java.lang.Object").getMethod("toString");m0 = Class.forName("java.lang.Object").getMethod("hashCode");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}

1.2 java.lang.reflect.InvocationHandler.invoke() spring.aop组装 jdk代理所需的参数

 /*** Implementation of {@code InvocationHandler.invoke}.* <p>Callers will see exactly the exception thrown by the target,* unless a hook method throws an exception.*/@Override@Nullablepublic 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 {if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.return equals(args[0]);}else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// The target does not implement the hashCode() method itself.return hashCode();}else if (method.getDeclaringClass() == DecoratingProxy.class) {// There is only getDecoratedClass() declared -> dispatch to proxy config.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...return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal;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.target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// 获取增强逻辑的advices// Get the interception chain for this method.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);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {// proxy:方法外部 Proxy.newInstance() 产出的代理实例// target:targetSource中保存的目标实例(在aop调用过程中维护Class实例)// method:java.lang.reflect.Method// args:方法参数// targetClass:target.getClass()// chain:增强逻辑advices// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// step into ...// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();}// Massage return value if necessary.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.AopContext.setCurrentProxy(oldProxy);}}}

1.3 spring.aop.MethodInvocation.proceed() 递归调用 advices

 @Override@Nullablepublic 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);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());if (dm.methodMatcher.matches(this.method, 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);}}

到这基本结束了,下面内容属于加餐选项

2. cglib代理类反编译源码

其实cglib除了生成代理类的字节码以外,还生成了 Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$xxxx 的字节码。初略的看了一下,果不其然,跟jdk代理一样,使用了 WeakCache 一类的弱缓存技术,只不过是cglib自己实现的。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.weng.cloud.sample.ctx;import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;public class SingleService$$EnhancerBySpringCGLIB$$cc775f74 extends SingleService implements Factory {private boolean CGLIB$BOUND;public static Object CGLIB$FACTORY_DATA;private static final ThreadLocal CGLIB$THREAD_CALLBACKS;private static final Callback[] CGLIB$STATIC_CALLBACKS;private NoOp CGLIB$CALLBACK_0;private MethodInterceptor CGLIB$CALLBACK_1;private MethodInterceptor CGLIB$CALLBACK_2;private static Object CGLIB$CALLBACK_FILTER;private static final Method CGLIB$protoService$0$Method;private static final MethodProxy CGLIB$protoService$0$Proxy;private static final Object[] CGLIB$emptyArgs;static void CGLIB$STATICHOOK3() {CGLIB$THREAD_CALLBACKS = new ThreadLocal();CGLIB$emptyArgs = new Object[0];Class var0 = Class.forName("com.weng.cloud.sample.ctx.SingleService$$EnhancerBySpringCGLIB$$cc775f74");Class var1;CGLIB$protoService$0$Method = ReflectUtils.findMethods(new String[]{"protoService", "()Lcom/weng/cloud/sample/ctx/ProtoService;"}, (var1 = Class.forName("com.weng.cloud.sample.ctx.SingleService")).getDeclaredMethods())[0];CGLIB$protoService$0$Proxy = MethodProxy.create(var1, var0, "()Lcom/weng/cloud/sample/ctx/ProtoService;", "protoService", "CGLIB$protoService$0");}final ProtoService CGLIB$protoService$0() {return super.protoService();}// 被增强的方法public final ProtoService protoService() {MethodInterceptor var10000 = this.CGLIB$CALLBACK_1;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_1;}// 调用增强逻辑 methodInterceptor.intercept()return var10000 != null ? (ProtoService)var10000.intercept(this, CGLIB$protoService$0$Method, CGLIB$emptyArgs, CGLIB$protoService$0$Proxy) : super.protoService();}public static MethodProxy CGLIB$findMethodProxy(Signature var0) {String var10000 = var0.toString();switch(var10000.hashCode()) {case 1187820471:if (var10000.equals("protoService()Lcom/weng/cloud/sample/ctx/ProtoService;")) {return CGLIB$protoService$0$Proxy;}}return null;}// 构造器public SingleService$$EnhancerBySpringCGLIB$$cc775f74() {// 初始化绑定关系(MethodInterceptor)CGLIB$BIND_CALLBACKS(this);}public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {CGLIB$THREAD_CALLBACKS.set(var0);}public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {CGLIB$STATIC_CALLBACKS = var0;}private static final void CGLIB$BIND_CALLBACKS(Object var0) {SingleService$$EnhancerBySpringCGLIB$$cc775f74 var1 = (SingleService$$EnhancerBySpringCGLIB$$cc775f74)var0;if (!var1.CGLIB$BOUND) {var1.CGLIB$BOUND = true;Object var10000 = CGLIB$THREAD_CALLBACKS.get();if (var10000 == null) {var10000 = CGLIB$STATIC_CALLBACKS;if (var10000 == null) {return;}}Callback[] var10001 = (Callback[])var10000;var1.CGLIB$CALLBACK_2 = (MethodInterceptor)((Callback[])var10000)[2];var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];var1.CGLIB$CALLBACK_0 = (NoOp)var10001[0];}}public Object newInstance(Callback[] var1) {CGLIB$SET_THREAD_CALLBACKS(var1);SingleService$$EnhancerBySpringCGLIB$$cc775f74 var10000 = new SingleService$$EnhancerBySpringCGLIB$$cc775f74();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;}public Object newInstance(Callback var1) {throw new IllegalStateException("More than one callback object required");}public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {CGLIB$SET_THREAD_CALLBACKS(var3);SingleService$$EnhancerBySpringCGLIB$$cc775f74 var10000 = new SingleService$$EnhancerBySpringCGLIB$$cc775f74;switch(var1.length) {case 0:var10000.<init>();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;default:throw new IllegalArgumentException("Constructor not found");}}public Callback getCallback(int var1) {CGLIB$BIND_CALLBACKS(this);Object var10000;switch(var1) {case 0:var10000 = this.CGLIB$CALLBACK_0;break;case 1:var10000 = this.CGLIB$CALLBACK_1;break;case 2:var10000 = this.CGLIB$CALLBACK_2;break;default:var10000 = null;}return (Callback)var10000;}public void setCallback(int var1, Callback var2) {switch(var1) {case 0:this.CGLIB$CALLBACK_0 = (NoOp)var2;break;case 1:this.CGLIB$CALLBACK_1 = (MethodInterceptor)var2;break;case 2:this.CGLIB$CALLBACK_2 = (MethodInterceptor)var2;}}public Callback[] getCallbacks() {CGLIB$BIND_CALLBACKS(this);return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2};}public void setCallbacks(Callback[] var1) {this.CGLIB$CALLBACK_0 = (NoOp)var1[0];this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1];this.CGLIB$CALLBACK_2 = (MethodInterceptor)var1[2];}static {CGLIB$STATICHOOK3();}
}

3. JOOR 封装jdk代理

简单带过一下,毕竟这个框架虽然好用,但并不受到广泛关注:

开源(目前在github维护)、轻量级(无第三方依赖)、支持链式调用 的 java反射库

3.1 先来个代理api的测试用例

    @DisplayName("官方MD中的代理用例")@Testvoid t1() {// 创建String的实例,同时作为 StringProxy的代理实例String stringProxy = Reflect.onClass(String.class.getName()).create(" hello world ")// step into ...// jdk代理api.as(StringProxy.class).substring(6);System.err.println(stringProxy);}

3.2 源码

    /*** Create a proxy for the wrapped object allowing to typesafely invoke methods* on it using a custom interface.** @param proxyType The interface type that is implemented by the proxy* @return A proxy for the wrapped object*/public <P> P as(Class<P> proxyType) {// step into ...return as(proxyType, new Class[0]);}/*** Create a proxy for the wrapped object allowing to typesafely invoke* methods on it using a custom interface.** @param proxyType The interface type that is implemented by the proxy* @param additionalInterfaces Additional interfaces that are implemented by*            the proxy* @return A proxy for the wrapped object*/@SuppressWarnings("unchecked")public <P> P as(final Class<P> proxyType, final Class<?>... additionalInterfaces) {final boolean isMap = (object instanceof Map);final InvocationHandler handler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String name = method.getName();// Actual method name matches always come firsttry {return on(type, object).call(name, args).get();}// [#14] Emulate POJO behaviour on wrapped map objectscatch (ReflectException e) {if (isMap) {Map<String, Object> map = (Map<String, Object>) object;int length = (args == null ? 0 : args.length);if (length == 0 && name.startsWith("get")) {return map.get(property(name.substring(3)));}else if (length == 0 && name.startsWith("is")) {return map.get(property(name.substring(2)));}else if (length == 1 && name.startsWith("set")) {map.put(property(name.substring(3)), args[0]);return null;}}if (method.isDefault()) {Lookup proxyLookup = null;// Java 9 versionif (CACHED_LOOKUP_CONSTRUCTOR == null) {// Java 9 version for Java 8 distribution (jOOQ Open Source Edition)if (proxyLookup == null)proxyLookup = onClass(MethodHandles.class).call("privateLookupIn", proxyType, MethodHandles.lookup()).call("in", proxyType).<Lookup> get();}// Java 8 versionelseproxyLookup = CACHED_LOOKUP_CONSTRUCTOR.newInstance(proxyType);return proxyLookup.unreflectSpecial(method, proxyType).bindTo(proxy).invokeWithArguments(args);}throw e;}}};Class<?>[] interfaces = new Class[1 + additionalInterfaces.length];interfaces[0] = proxyType;System.arraycopy(additionalInterfaces, 0, interfaces, 1, additionalInterfaces.length);// 原汁原味return (P) Proxy.newProxyInstance(proxyType.getClassLoader(), interfaces, handler);}

spring.aop 随笔4 如何借助jdk代理类实现aop相关推荐

  1. Spring框架学习笔记(7)——代理对象实现AOP

    AOP(面向切面编程) AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming ...

  2. spring AbstractBeanDefinition创建bean类型是动态代理类的方式

    1.接口 Class<?> resourceClass 2.获取builder BeanDefinitionBuilder builder = BeanDefinitionBuilder. ...

  3. 【Spring AOP】AOP 底层实现原理 —— 动态代理类的创建(JDK、CGlib)、工厂如何加工原始对象

    AOP编程 AOP 编程 AOP 概念 AOP 编程的开发步骤 切面的名词解释 AOP 的底层实现原理 动态代理类的创建 JDK 的动态代理(原理 + 编码) CGlib 的动态代理 Spring 工 ...

  4. spring service ,controller反向代理生成AOP代理类流程

    一.在applicationContext的beanFactory.preInstantiateSingletons方法中,会初始化所有的单例BEAN. 二. 1.AbstractAutowireCa ...

  5. Spring→面向切面编程AOP、相关概念、通知Advice类型、配置切面切入点通知、AOP相关API、AOP代理类ProxyFactoryBean、AOP注解@AspectJ

    面向切面编程AOP CGLib AOP相关概念 Advice类型 Spring实现AOP Spring配置切面aspect 配置切入点pointcut 配置通知advice 配置通知参数 调用新的父类 ...

  6. 《Spring参考手册》中定义了以下几个AOP的重要概念

    from: http://pandonix.iteye.com/blog/336873 <Spring参考手册>中定义了以下几个AOP的重要概念,结合以上代码分析如下: 切面(Aspect ...

  7. spring boot 项目 事务 不能回滚 代理(not eligible for auto-proxying)

    spring 事务机制网上的案例很多,关于事务 不能回滚也有很多的类型,不同的问题有不同的处理方案,本篇博客主要介绍两种事务不能回滚的问题解决方案: 问题一: 在同一个对象中有两个方法,分别未方法A, ...

  8. 子类重写方法aop切不到_SpringBoot源码之旅——AOP

    前提 本文代码基于SpringBoot的2.1.1.RELEASE版本,基于@AspectJ注解的AOP. 理解AOP,需要先搞懂Spring IoC容器,bin17:SpringBoot源码之旅-- ...

  9. Spring4:没有默认构造函数的基于CGLIB的代理类

    在Spring中,如果要代理的目标对象的类未实现任何接口,则将创建基于CGLIB的代理. 在Spring 4之前,基于CGLIB的代理类需要默认的构造函数. 这不是CGLIB库的限制,而是Spring ...

最新文章

  1. .net反射详解(转)
  2. 引号快捷键_干货收藏|excel2016常用快捷键
  3. bzoj2337: [HNOI2011]XOR和路径
  4. KeyMob移动广告聚合平台:类似于房地产中介
  5. IOS中实现设备摇动检测
  6. Java字符编码的转化问题
  7. 全球及中国煤炭工业市场产量规模与十四五发展战略报告2022版
  8. 牛客 - Colorful Tree(dfs序+LCA)
  9. java创建子类对象的步骤_一顿Spring骚操作:我敢说没有人比我更懂Java对象的创建!
  10. 第2章 一切都是对象
  11. java java 大端_Java 大小端转换
  12. 运行时数据区——Java虚拟机栈
  13. 啥?!BM25 比语义向量检索效果好?
  14. 多线程的处理 handler   handlerTread Intentservice
  15. “为爱尖叫”,爱奇艺的晚会聚能术与商业价值释放场
  16. 计算机一级仿宋gb2312,2016年计算机一级Office考试题(带答案)
  17. 小学数学计算机按键名称,数学计算器
  18. ① 数据库介绍 及 关系型数据库的关系代数表达式
  19. 2.5、信道的极限容量!
  20. java像素鸟素材_像素鸟FlappyBird素材(图片+音乐)

热门文章

  1. 写出一个程序,接受一个由字母、数字和空格组成的字符串,和一个字符,然后输出输入字符串中该字符的出现次数。(不区分大小写字母)
  2. Windows如何查看文件夹大小:使用 DirPrintOK
  3. Python编程挑战100题:12读取成绩文件排序数据
  4. 用户编号与计算机绑定,手机绑定了什么怎么查-太平洋IT百科手机版
  5. 行业巨头的没落,网易听说过没?
  6. 什么是 window 对象?什么是 document 对象?
  7. Python调用默认浏览器打开网页
  8. 红米note2刷机包(2015052)解账户锁
  9. 启中教育:新手开网店怎么做好准备工作
  10. 阿里云发布行业首个「视频直播技术最佳实践图」!