diff --git "a/docs/study/Java/\343\200\212bytebuddy\350\277\233\351\230\266\345\256\236\346\210\230\343\200\213-\345\255\246\344\271\240\347\254\224\350\256\260.md" "b/docs/study/Java/\343\200\212bytebuddy\350\277\233\351\230\266\345\256\236\346\210\230\343\200\213-\345\255\246\344\271\240\347\254\224\350\256\260.md"
index 027d2ae..a7c275f 100644
--- "a/docs/study/Java/\343\200\212bytebuddy\350\277\233\351\230\266\345\256\236\346\210\230\343\200\213-\345\255\246\344\271\240\347\254\224\350\256\260.md"
+++ "b/docs/study/Java/\343\200\212bytebuddy\350\277\233\351\230\266\345\256\236\346\210\230\343\200\213-\345\255\246\344\271\240\347\254\224\350\256\260.md"
@@ -554,5 +554,638 @@ public class MysqlInstrumentation extends AbstractClassEnhancePluginDefine {
}
```
-##
+## 4.5 阶段四: 拦截器逻辑
+
+### 4.5.1 目标
+
+完善插件的拦截器逻辑,具体包括拦截的方法范围,拦截后的拦截器增强逻辑
+
+### 4.5.2 代码实现和思考
+
+#### 4.5.2.1 拦截器内部逻辑抽象
+
+SkyWalking对拦截器内的具体逻辑进行抽象,只需要开发者根据拦截方法的类型实现拦截器接口方法。
+
++ `InstanceMethodAroundInterceptor`:实例方法拦截器接口,所有插件中的实例方法拦截器需要实现该接口
++ `ConstructorInterceptor`:构造方法拦截器接口,所有插件中的构造方法拦截器需要实现该接口
++ `StaticMethodAroundInterceptor`:静态方法拦截器接口,所有插件中的静态方法拦截器需要实现该接口
+
+这里拿`InstanceMethodAroundInterceptor`代码举例:
+
++ `beforeMethod`:在被增强的实例方法之前执行
+
++ `afterMethod`:相当于被增强的实例方法的finally中执行
++ `handleEx`:被增强的方法出现异常时执行
+
+```java
+package org.example.core.interceptor.enhance;
+
+import java.lang.reflect.Method;
+
+/**
+ * 实例方法(不包括 构造方法) 的拦截器 都需要实现当前接口
+ * @author : Ashiamd email: ashiamd@foxmail.com
+ * @date : 2023/12/31 6:37 PM
+ */
+public interface InstanceMethodAroundInterceptor {
+ /**
+ * 前置增强逻辑
+ */
+ void beforeMethod(EnhancedInstance obj, Method method, Object[] allArgs, Class>[] parameterTypes);
+
+ /**
+ * finally 后置增强逻辑 (不管原方法是否异常都会执行)
+ * @return 方法返回值
+ */
+ Object afterMethod(EnhancedInstance obj, Method method, Object[] allArgs, Class>[] parameterTypes, Object returnValue);
+
+ /**
+ * 异常处理
+ */
+ void handleEx(EnhancedInstance obj, Method method, Object[] allArgs, Class>[] parameterTypes, Throwable t);
+}
+```
+
+思考:
+
+1. 拦截器内部逻辑分类?
+
+ 本身开发Byte Buddy拦截器时,对实例方法、构造方法、静态方法的拦截器处理逻辑不同,所以分成3类很合理
+
+2. 拦截器内部逻辑抽象的方式?
+
+ 从接口定义不难看出来,很像常见的AOP切面开发。个人觉得这是一种经验总结后得到的开发模式。即大部分人在进行方法增强时,一般也就是在方法之前、方法执行后,以及出现异常时,执行我们自己的拦截器逻辑。
+
+#### 4.5.2.2 拦截器模版
+
+使用ByteBuddy指定拦截的方法范围后,需要指定使用的拦截器,而拦截器的实现基本都是套路化了,SkyWalking也是为构造方法、实例方法、静态方法提供了具体的拦截器模版实现。
+
++ `ConstructorInter`:构造方法拦截器模版
++ `InstanceMethodsInter`:实例方法拦截器模版
++ `StaticMethodsInter`:静态方法拦截器模版
+
+这里以`StaticMethodsInter`举例:
+
++ `intercept`方法,ByteBuddy执行拦截的目标方法时,会调用该拦截逻辑。可以看出来里面用到了插件具体实现的拦截器逻辑,而整体的调用链路基本都是套路,所以直接模版化实现
+
+```java
+package org.example.core.interceptor.enhance;
+
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.implementation.bind.annotation.AllArguments;
+import net.bytebuddy.implementation.bind.annotation.Origin;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+import net.bytebuddy.implementation.bind.annotation.SuperCall;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+/**
+ * 通用的静态方法拦截器
+ *
+ * @author : Ashiamd email: ashiamd@foxmail.com
+ * @date : 2023/12/31 6:27 PM
+ */
+@Slf4j
+public class StaticMethodsInter {
+ /**
+ * 拦截器在各个位置执行某些逻辑,封装在此成员变量中
+ */
+ private StaticMethodAroundInterceptor interceptor;
+
+ public StaticMethodsInter(String methodsInterceptorName, ClassLoader classLoader) {
+ }
+
+
+ /**
+ * 具体的拦截器逻辑, 整体预留的填充逻辑和AOP切面编程类似
+ */
+ @RuntimeType
+ public Object intercept(
+ // 被拦截的目标类
+ @Origin Class> clazz,
+ // 被拦截的目标方法
+ @Origin Method method,
+ // 方被拦截的方法的法参数
+ @AllArguments Object[] allArgs,
+ // 调用原被拦截的目标方法
+ @SuperCall Callable> zuper) throws Throwable {
+ // 1. 前置增强
+ try {
+ interceptor.beforeMethod(clazz, method, allArgs, method.getParameterTypes());
+ } catch (Throwable e) {
+ log.error("Static Method Interceptor: {}, enhance method: {}, before method failed, e: ", interceptor.getClass().getName(), method.getName(), e);
+ }
+ Object returnValue = null;
+ try {
+ returnValue = zuper.call();
+ } catch (Throwable e) {
+ // 2. 异常处理
+ try {
+ interceptor.handleEx(clazz, method, allArgs, method.getParameterTypes(), e);
+ } catch (Throwable innerError) {
+ log.error("Static Method Interceptor: {}, enhance method: {}, handle Exception failed, e: ", interceptor.getClass().getName(), method.getName(), e);
+ }
+ // 继续上抛异常, 不影响原方法执行逻辑
+ throw e;
+ } finally {
+ // 3. 后置增强
+ try {
+ returnValue = interceptor.afterMethod(clazz, method, allArgs, method.getParameterTypes(), returnValue);
+ } catch (Throwable e) {
+ log.error("Static Method Interceptor: {}, enhance method: {}, after method failed, e: ", interceptor.getClass().getName(), method.getName(), e);
+ }
+ }
+ return returnValue;
+ }
+}
+```
+
+#### 4.5.2.3 插件规范
+
+前面的 "4.4.2.1 插件规范"中,只要求插件声明自己需要拦截的类范围,以及拦截点(拦截的方法范围和拦截器类名),但是并没有定义如何执行增强逻辑。
+
+这里对插件规范进一步完善,规范定义了插件进行类增强的执行流程。
+
++ `AbstractClassEnhancePluginDefine`:所有插件的顶级父类
++ `ClassEnhancePluginDefine`:所有插件的父类,指定具体的transform逻辑(拦截的方法范围,以及拦截器逻辑指定)
+
+1. `AbstractClassEnhancePluginDefine`
+
++ `CONTEXT_ATTR_NAME`:增强实例方法/构造方法时,给目标类新增的成员变量的变量名,用于拦截器`beforeMethod`, `afterMethod`, `handleEx`之间传递中间值
++ `define`:定义方法的增强逻辑(包括绑定增强的方法范围,以及使用的拦截器)
++ `enhance`:具体的增强逻辑,包括增强构造方法、实例方法、静态方法
+ + `enhanceInstance`:增强实例方法和构造方法,包括绑定方法拦截范围和拦截器指定
+ + `enhanceClass`:增强静态方法,包括绑定方法拦截范围和拦截器指定
+
+```java
+package org.example.core;
+
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.dynamic.DynamicType;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.example.core.interceptor.ConstructorMethodsInterceptorPoint;
+import org.example.core.interceptor.InstanceMethodsInterceptorPoint;
+import org.example.core.interceptor.StaticMethodsInterceptorPoint;
+import org.example.core.match.ClassMatch;
+
+/**
+ * 所有插件的顶级父类
+ *
+ * @author : Ashiamd email: ashiamd@foxmail.com
+ * @date : 2023/12/30 6:10 PM
+ */
+@Slf4j
+public abstract class AbstractClassEnhancePluginDefine {
+
+ /**
+ * 为匹配到的字节码(类)新增的成员变量的名称
+ */
+ public static final String CONTEXT_ATTR_NAME = "_$EnhancedClassField_ws";
+
+ /**
+ * 表示当前插件要拦截/增强的类范围
+ * 相当于对应 {@link AgentBuilder#type(ElementMatcher)} 的 参数 {@code ElementMatcher super TypeDescription>}
+ */
+ protected abstract ClassMatch enhanceClass();
+
+ /**
+ * 实例方法的拦截点
+ * ps: 类下面多个方法可能使用不同的拦截器
+ */
+ protected abstract InstanceMethodsInterceptorPoint[] getInstanceMethodsInterceptorPoints();
+
+ /**
+ * 构造方法的拦截点
+ */
+ protected abstract ConstructorMethodsInterceptorPoint[] getConstructorMethodsInterceptorPoints();
+
+ /**
+ * 静态方法的拦截点
+ * ps: 类下面多个方法可能使用不同的拦截器
+ */
+ protected abstract StaticMethodsInterceptorPoint[] getStaticMethodsInterceptorPoints();
+
+ /**
+ * 增强类的主入口,绑定 当前类中哪些方法被拦截+具体的拦截器逻辑 到 builder(后续链式调用会把所有插件的配置都绑定上)
+ */
+ public DynamicType.Builder> define(TypeDescription typeDescription,
+ DynamicType.Builder> builder,
+ ClassLoader classLoader,
+ EnhanceContext enhanceContext) {
+ log.info("类: {}, 被插件: {} 增强 -- start", typeDescription, this.getClass().getName());
+ DynamicType.Builder> newBuilder = this.enhance(typeDescription, builder, classLoader, enhanceContext);
+ // 表示 当前类已经被增强过了
+ enhanceContext.initializationStageCompleted();
+ log.info("类: {}, 被插件: {} 增强 -- end", typeDescription, this.getClass().getName());
+ return newBuilder;
+ }
+
+ /**
+ * 具体的增强逻辑
+ */
+ private DynamicType.Builder> enhance(TypeDescription typeDescription,
+ DynamicType.Builder> newBuilder,
+ ClassLoader classLoader,
+ EnhanceContext enhanceContext) {
+ // 1. 静态方法增强
+ newBuilder = this.enhanceClass(typeDescription, newBuilder, classLoader);
+ // 2. 实例方法增强(包括构造方法)
+ newBuilder = this.enhanceInstance(typeDescription, newBuilder, classLoader, enhanceContext);
+ return newBuilder;
+ }
+
+ /**
+ * 实例方法增强(包括构造方法)
+ */
+ protected abstract DynamicType.Builder> enhanceInstance(TypeDescription typeDescription,
+ DynamicType.Builder> newBuilder,
+ ClassLoader classLoader,
+ EnhanceContext context);
+
+ /**
+ * 静态方法增强
+ */
+ protected abstract DynamicType.Builder> enhanceClass(TypeDescription typeDescription,
+ DynamicType.Builder> newBuilder,
+ ClassLoader classLoader);
+}
+```
+
+2. `ClassEnhancePluginDefine`
+
++ `enhanceInstance`:遍历实例方法拦截点和构造方法拦截点,通过Byte Buddy绑定拦截的方法范围和对应的拦截器,并且头一次增强时新增用于传递中间值的成员变量。
++ `enhanceClass`:遍历静态方法拦截点,绑定拦截的方法范围和对应的拦截器
+
+```java
+package org.example.core.interceptor.enhance;
+
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.dynamic.DynamicType;
+import net.bytebuddy.implementation.FieldAccessor;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.implementation.SuperMethodCall;
+import net.bytebuddy.jar.asm.Opcodes;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.example.core.AbstractClassEnhancePluginDefine;
+import org.example.core.EnhanceContext;
+import org.example.core.interceptor.ConstructorMethodsInterceptorPoint;
+import org.example.core.interceptor.InstanceMethodsInterceptorPoint;
+import org.example.core.interceptor.StaticMethodsInterceptorPoint;
+
+import static net.bytebuddy.matcher.ElementMatchers.isStatic;
+import static net.bytebuddy.matcher.ElementMatchers.not;
+
+/**
+ * 所有插件直接or间接继承当前类, 当前类完成具体的增强逻辑(transform的方法拦截范围指定,以及拦截器指定)
+ *
+ * 当前类的作用相当于: + * {@code DynamicType.Builder> newBuilder = builder.method(xx).intercept(MethodDelegation.to(xx))} + *
+ * + * @author : Ashiamd email: ashiamd@foxmail.com + * @date : 2023/12/31 5:57 PM + */ +@Slf4j +public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePluginDefine { + @Override + protected DynamicType.Builder> enhanceInstance(TypeDescription typeDescription, DynamicType.Builder> newBuilder, ClassLoader classLoader, EnhanceContext context) { + ConstructorMethodsInterceptorPoint[] constructorPoints = getConstructorMethodsInterceptorPoints(); + InstanceMethodsInterceptorPoint[] instanceMethodPoints = getInstanceMethodsInterceptorPoints(); + // 构造方法拦截点是否存在 + boolean existedConstructorPoint = null != constructorPoints && constructorPoints.length > 0; + // 实例方法拦截点是否存在 + boolean existedInstanceMethodPoint = null != instanceMethodPoints && instanceMethodPoints.length > 0; + if (!existedConstructorPoint && !existedInstanceMethodPoint) { + // 都不存在,则拦截的类范围内,没有需要拦截器增强的方法 + return newBuilder; + } + + // 如果是头一次增强当前类, 则新增用于传递中间值的成员变量 (如果还没实现EnhanceContext接口,且没有新增过字段,则新增) + if(!typeDescription.isAssignableFrom(EnhanceContext.class) + && !context.isObjectExtended()) { + newBuilder + // 新增成员变量,用于拦截器逻辑传递中间值 + .defineField(CONTEXT_ATTR_NAME,Object.class, Opcodes.ACC_PRIVATE | Opcodes.ACC_VOLATILE) + // 实现 getter, setter接口 + .implement(EnhancedInstance.class) + .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)); + // 当前类已经拓展过(新增过成员变量) + context.objectExtendedCompleted(); + } + + // 1.构造方法增强 + if(existedConstructorPoint) { + String typeName = typeDescription.getTypeName(); + for (ConstructorMethodsInterceptorPoint constructorPoint : constructorPoints) { + String constructorInterceptorName = constructorPoint.getConstructorInterceptor(); + if (null == constructorInterceptorName || "".equals(constructorInterceptorName.trim())) { + log.error("插件: {} 没有指定目标类: {} 的构造方法对应的拦截器", this.getClass().getName(), typeName); + } + ElementMatcher