Modo agencia:
El modo proxy también es una implementación del principio de apertura y cierre. La función se extiende sin cambiar el código fuente, y el objeto de destino está encapsulado por el objeto de proxy, que oculta el objeto de destino y realiza una preventa del original. Función postventa; Spring Aop es un modelo típico de agencia
Modo proxy estático:
// 目标对象和代理对象实现同一个接口 interface Interface01{ void fun01(); } // 目标对象 class TargetClass implements Interface01{ @Override public void fun01() { System.out.println("执行目标对象函数"); } } // 代理对象 class ProxyClass implements Interface01{ // 目标对象 private TargetClass targetClass ; // 有参构造器(传入一个目标对象的实例) public ProxyClass(TargetClass targetClass) { this.targetClass = targetClass; } // 执行方法 @Override public void fun01() { System.out.println("执行前***"); targetClass.fun01(); System.out.println("执行后***"); } }
Proxy dinámico:
Dado que los agentes estáticos necesitan una clase de proxy cada vez, aparece un proxy dinámico y la clase de proxy se crea de forma dinámica
Proxy dinámico compatible con j'd'k: el proxy dinámico de jdk se basa en interfaces y la clase de destino debe implementar una interfaz, pero de hecho no todas las clases tienen una interfaz.
public class TestDynamicProxy {
public static void main(String[] args) {
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new TargetDncymicClass());
// 获取代理对象
Interface02 proxy = (Interface02) myInvocationHandler.getProxy();
proxy.fun02();
}
}
// 接口
interface Interface02{
void fun02();
}
// 目标类
class TargetDncymicClass implements Interface02{
@Override
public void fun02() {
System.out.println("TargetDncymicClass...");
}
}
// invocationHandler
class MyInvocationHandler implements InvocationHandler{
private Object target;
// 传入目标对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前。。");
// 执行目标方法
Object object = method.invoke(target, args);
System.out.println("执行后。。");
return object;
}
// 获取生成的代理对象
public Object getProxy() {
// 参数1 类加载器,参数2 目标类的所有实现接口, 参数3 InvocationHandler
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
}
Cglib:
El proxy dinámico implementado por cglib no requiere que la clase de destino implemente la interfaz, y la capa inferior usa código de bytes asm para generar el código de bytes de la clase de proxy.
// 定义目标类
class TargetCglibClass{
// 目标方法
public void test() {
System.out.println("TargetCglibClass...");
}
// methodInterceptor 方法拦截器
class MyMethodInterceptor implements MethodInterceptor{
@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;
}
}
//测试
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetCglibClass.class);
enhancer.setCallback(new MyMethodInterceptor());
TargetCglibClass o = (TargetCglibClass) enhancer.create();
o.test();
}
La diferencia entre la implementación de proxy dinámico jdk y cglib
1. La clase de proxy y la clase delegada generada por el proxy dinámico jdk implementan la misma interfaz;
2. El código de bytes generado en el proxy dinámico cglib es más complicado. La clase de proxy generada es una subclase de la clase delegada y no puede manejar palabras clave finales
.Método modificado: 3. jdk usa el mecanismo de reflexión para llamar al método de la clase delegada, y cglib usa el método similar al índice para llamar directamente al método de la clase delegada;