Динамический прокси CGLIB
что такое cglib?
CGLIB (библиотека генерации кода) — это проект с открытым исходным кодом!
Это мощная, высокопроизводительная и высококачественная библиотека генерации кода, которая может расширять классы Java и реализовывать интерфейсы Java во время выполнения.
CGLIB — это мощный высокопроизводительныйгенерация кодаМешок. Он широко используется многими средами АОП, такими как Spring AOP и dynaop, для обеспечения перехвата их методов. Самый популярный инструмент OR Mapping, hibernate, также использует CGLIB для проксирования односторонних (многие к одному и один к одному) ассоциаций (отложенная выборка коллекций, реализованная с использованием других механизмов). EasyMock иjMock— это пакет для тестирования Java-кода с использованием фиктивных объектов. Оба они используют CGLIB для создания фиктивных объектов для классов, не имеющих интерфейсов.
CGLIIB реализует динамический прокси
Сначала зайдите на сервис Обратите внимание, что нет интерфейса
public class CglibService {
public CglibService() {
System.out.println("CglibDao 构造方法");
}
/**
* 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的
* @param name
* @return
*/
final public String sayOthers(String name){
System.out.println("CglibDao final sayOthers:"+name);
return null;
}
public void sayHello(){
System.out.println("CglibDao:sayHello");
}
}
Создайте новый Interceptor для реализации org.springframework.cglib.proxy.MethodInterceptor
public class MyMethodInterceptor implements MethodInterceptor {
/**
*
* @param o 代理对象
* @param method 被代理的对象方法
* @param objects 方法入参
* @param methodProxy 代理方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("======插入前置通知======");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("======插入后置通知======");
return object;
}
}
Новый тестовый класс
/**
* cglib 动态代理测试
*/
public class cglibAgentTest {
@Test
public void testCglibAgent(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CglibService.class);
// 设置enhancer的回调对象
enhancer.setCallback(new MyMethodInterceptor());
// 创建代理对象
CglibService proxy= (CglibService)enhancer.create();
// 通过代理对象调用目标方法
proxy.sayHello();
proxy.sayOthers("小明");
}
}
напечатанное значение
CglibDao 构造方法
======插入前置通知======
CglibDao:sayHello
======插入后置通知======
CglibDao final sayOthers:小明
Видно, что его конструктор будет выполняться первым, при вызове sayHello первым будет вызываться их прокси-метод, если метод окончательный, то прокси не может быть реализован.
Суммировать
Разница между Cglib и динамическим прокси, реализованным InvocationHandler, заключается в том, что cglib не нужно писать интерфейс
AOP в Spring также можно настроить в режиме Cglib.
В дополнение к пакету CGLIB языки сценариев, такие как Groovy и BeanShell, также используют ASM для генерации байт-кода Java. Конечно, прямое использование ASM не рекомендуется.
Поскольку это требует от вас знакомства с внутренней структурой JVM, включая формат и набор инструкций файла класса, рекомендуется использовать Cglib