1. Что такое CGLIB?
В общем, будь то cglib, динамический прокси jdk или аспектно-ориентированное программирование aop, используется один из самых важных паттернов проектирования — паттерн прокси! Изменения неразделимы, хорошо изучите режим агента и будьте непобедимы во всем мире!
cglib — это байт-код生成
и转换
библиотека! Это нетрудно понять, он в основном используется АОП, средами тестирования и доступа к данным для создания динамических代理对象
и拦截字段访问
.
Сегодня мы поговорим о применении cglib в прокси!
Во-вторых, грубая интерпретация исходного кода CGLIB!
Во-первых, давайте взглянем на структуру пакета исходного кода cglib:
Из основного пакета cglib вы можете видеть, что существуетproxy
сумка, давайте узнаем вместе! расширятьproxy
Его можно найти:
в упаковкеEnhancer
класс иMethodInterceptor
Интерфейс — это сердце всего пакета!Enhancer
Это означает «улучшение»! В основном используется для создания动态子类
включить перехват метода, что это значит? Говори так! Основная идея прокси класса cglib состоит в том, чтобы сгенерировать новый класс для класса прокси (proxy
), класс наследуется от проксируемого класса и выполняет некоторые операции до и после выполнения метода проксируемого класса.Эти операции обычно являются некоторыми операциями обратного вызова, которые могут бытьMethodInterceptor
,LazyLoader
,CallbackFilter
,вMethodInterceptor
является наиболее часто используемым.
все былиEnhancer
Связанные объекты реализованы по умолчаниюFactory
Интерфейс, который предоставляет набор методов, которые могут установить тип обратного вызова объекта, вы можете вызватьsetUseFactory(false)
Отмените эту функцию!
Следует отметить, что cglib нельзя проксироватьfinal
Модифицированный метод, потому что это определяется спецификацией языка java!
MethodInterceptor
является положением环绕通知
Общий интерфейс обратного вызова! В Аоп есть такой термин, т.е.前置通知
,后置通知
,环绕通知
, очень легко понять, это уведомление до выполнения метода, уведомление после выполнения метода, а другое — уведомление до и после выполнения метода.
Есть только один интерфейсintercept()
метод:
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
MethodProxy proxy) throws Throwable;
Все выполнение метода прокси-класса перейдет к этому методу, а исходный метод получается через отражениеMethod
объект илиMethodProxy
объект для вызова.
Три, старые правила, приходят к каштану, чтобы воссоединиться вместе!
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
class Student {
private String name = "zhangsan";
public String getStuName() {
return name;
}
}
public class CglibMethodInterceptTest {
public static void main(String[] args) {
//创建一个Enhancer对象
Enhancer enchaner = new Enhancer();
//设置被代理的类
enchaner.setSuperclass(Student.class);
//创建一个回调接口
Callback interceptor = new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.err.println("原方法名是 : " + method.getName());
System.err.println("原方法声明的类为 " + method.getDeclaringClass());
System.err.println("我是 " + (String) proxy.invokeSuper(obj, args));
System.err.println("我调用结束了");
return null;
}
};
enchaner.setCallback(interceptor);
Student student = (Student) enchaner.create();
student.getStuName();
}
}
Результат:
原方法名是 : getStuName
原方法声明的类为 class wokao666.test.Student
我是 zhangsan
我调用结束了
过滤器的使用
package wokao666.test;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.NoOp;
class Student {
private String name = "zhangsan";
private String rename = "rename";
public String getStuName() {
return name;
}
public String getRename() {
return rename;
}
}
public class CglibMethodInterceptTest {
public static void main(String[] args) {
//创建一个Enhancer对象
Enhancer enchaner = new Enhancer();
//设置被代理的类
enchaner.setSuperclass(Student.class);
//创建一个回调接口
Callback interceptor = new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.err.println("原方法名是 : " + method.getName());
System.err.println("原方法声明的类为 " + method.getDeclaringClass());
System.err.println("我是 " + (String) proxy.invokeSuper(obj, args));
System.err.println("我调用结束了");
return proxy.invokeSuper(obj, args);
}
};
CallbackFilter callbackFilter = new CallbackFilter() {
@Override
public int accept(Method method) {
int flag = 0;
if ("getStuName".equals(method.getName())) {
System.err.println("我将此方法过滤掉了,不对该方法进行拦截");
return 1;
}
return 0;
}
};
Callback[] callbacks = new Callback[] { interceptor, NoOp.INSTANCE };
enchaner.setCallbackFilter(callbackFilter);
enchaner.setCallbacks(callbacks);
Student student = (Student) enchaner.create();
System.err.println(student.getStuName());
System.err.println(student.getRename());
}
}
我将此方法过滤掉了,不对该方法进行拦截
zhangsan
原方法名是 : getRename
原方法声明的类为 class wokao666.test.Student
我是 rename
我调用结束了
rename
NoOp.INSTANCE
:этоNoOp
выражатьno operator
, то есть ничего не делать, а прокси-класс напрямую вызывает прокси-метод, не перехватывая его.
getStuName
Индекс 1, определенный в соответствующем CallbackFilter, вCallback[]
Фильтр, используемый в массиве,NoOp
, поэтому делегированный метод выполняется напрямую.
getRename
В соответствии с индексом 0, определенным в CallbackFilter, вCallback[]
Фильтр, используемый в массиве,interceptor
, поэтому перехватчик метода выполняется для перехвата.
То, что я написал, это просто немного кожи.Я предлагаю вам сделать больше на этой основе, и написать больше примеров в сочетании с исходным кодом.Чем больше вы пишете, тем больше вы понимаете!