Во-первых, принцип реализации
-
Используя пакет с открытым исходным кодом ASM, загрузите файл класса реального класса объекта, сгенерируйте его подкласс, изменив байт-код, и перезапишите соответствующий метод родительского класса.
Примечание: ASM — это платформа для прямого управления байт-кодом.
2. Метод реализации
- 1) Определите обработчик перехвата. Реализуйте интерфейс MethodInterceptor и переопределите метод перехвата для обработки перехвата.
- 2) Создание динамических прокси-классов. Измените байт-код файла класса прокси-объекта, чтобы сгенерировать подкласс.
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
</dependency>
package com.java24k.example.target;
/**
* @Description: 真实主题即被代理对象
* @Author zhoufeng
* @Date 2020/7/13 2:34
* @version: V1.0
*/
public class TargetClass {
public void targetInfo(){
System.out.println("打印目标类信息");
}
}
package com.java24k.example.interceptor;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Description: 代理拦截处理器
* @Author zhoufeng
* @Date 2020/7/13 2:30
* @version: V1.0
*/
public class MyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("------插入前置通知代码-------------");
// 此处一定要使用proxy的invokeSuper方法来调用目标类的方法
methodProxy.invokeSuper(o, objects);
System.out.println("------插入后置处理代码-------------");
return null;
}
}
package com.java24k.example.test;
import com.java24k.example.interceptor.MyInterceptor;
import com.java24k.example.target.TargetClass;
import net.sf.cglib.proxy.Enhancer;
/**
* @Description: 生成cglib代理测试类
* @Author zhoufeng
* @Date 2020/7/13 2:41
* @version: V1.0
*/
public class CglibProxyTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
// 设置目标类
enhancer.setSuperclass(TargetClass.class);
// 设置拦截器对象
enhancer.setCallback(new MyInterceptor());
// 创建子类 即代理
TargetClass targetClassProxy = (TargetClass) enhancer.create();
targetClassProxy.targetInfo();
}
}
------插入前置通知代码-------------
打印目标类信息
------插入后置处理代码-------------
Process finished with exit code 0
3. Механизм FastClass
В динамическом прокси JDK метод вызова целевого объекта использует отражение, а в динамическом прокси CGLIB используется механизм FastClass.
- Использование FastClass: динамически генерируйте класс, который наследует FastClass, записывайте объект делегата в класс и напрямую вызывайте метод объекта делегата.
- Логика FastClass: В динамическом классе, наследующем FastClass, индекс метода получается в соответствии с сигнатурой метода (имя метода + параметры метода), а метод целевого объекта вызывается в соответствии с индексом метода.
- Преимущества FastClass: FastClass используется для замены отражения Java, что позволяет избежать проблемы медленных вызовов, вызванных отражением.
Во втором и третьем разделах мы проанализируем CGLIB для создания исходного кода динамического прокси и исходного кода FastClass.