上海工商网站查询企业信息,商城网站后续费用,学做网站有用吗,在门户网站建设上的讲话前言
动态代理可以说是Java基础中一个比较重要的内容#xff0c;这块内容关系到Spring框架中的AOP实现原理#xff0c;所以特别写了一篇作为个人对这块知识的总结。这部分内容主要包括#xff1a;JDK Proxy和CGLib的基本介绍、二者的实现原理、代码示例等。
什么是动态代理…前言
动态代理可以说是Java基础中一个比较重要的内容这块内容关系到Spring框架中的AOP实现原理所以特别写了一篇作为个人对这块知识的总结。这部分内容主要包括JDK Proxy和CGLib的基本介绍、二者的实现原理、代码示例等。
什么是动态代理
动态代理是指程序在运行过程中动态代理的实现是基于某个特点类而生成的增强类也就是说动态代理生成的类会顶替掉原来的类而被执行从而做到达到增强的目前
目前流行的动态代理机制有两种JDK Proxy 和 CGLIB
这两个人实现动态代理的方式不同前者是要求被代理类必须继承接口而后者则没有这个要求因为他是通过生成代理类的子类来进行构造的。
JDK Proxy
JDK Proxy 是Java官方提供的一种动态代理类实现方式它的实现动态代理特点如下
代理类实现接口通过反射生产代理类
为什么被代理类要实现接口
可能有人会有疑惑为什么说JDK Proxy仅支持实现了接口的被代理类这个问题需要分几点来回答
【首先】生成的代理类是通过反射的方式构建的这个过程中这个代理类可以认为就是被代理类的“克隆体”但是与之不同的其中一个点的是这个生产的代理类也需要继承Proxy才行但是假如被代理类继承了其他类但是Java中是不允许多继承的所以被代理类是不能继承其他类否则就会出现多继承的错误
【其次】在Java中实现接口和继承类是不冲突的为了在生产代理类后我们可以拿到被代理类的同名方法然后进行重写重写内容后续说明所以JDK Proxy选择了实现接口的这种方式
代码示例
以下是动态代理的一个代码示例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 定义接口
interface UserService {void save();
}// 实现接口的具体类
class UserServiceImpl implements UserService {public void save() {System.out.println(Save user);}
}// 实现InvocationHandler接口来自定义代理逻辑
class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(Before method);Object result method.invoke(target, args);System.out.println(After method);return result;}
}public class Main {public static void main(String[] args) {UserService userService new UserServiceImpl();// 创建InvocationHandler对象MyInvocationHandler handler new MyInvocationHandler(userService);// 通过Proxy类的静态方法创建代理对象UserService proxy (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),handler);// 调用代理对象的方法proxy.save();}
}在这段代码中
【1】我们先看接口和被代理类实现比较简单接口实现类重写接口方法。
【2】MyInvocationHandler是一个接口实现类它的目的是为了创建自定义的代理规则逻辑target属性就是被代理类MyInvocationHandler的构造方法必须将被代理对象的引用传递进来然后进行属性赋值
【3】MyInvocationHandler中的invoke()方法是最核心的它才是实现动态代理规则逻辑的主要部分
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(Before method);Object result method.invoke(target, args);System.out.println(After method);return result
}在这个方法中method.invoke这个语句就是我们被代理类的方法执行这个方法中通过传递被代理类target在内部调用这个被代理类的方法然后在metho.invoke方法上下就可以执行其他前置后置增强逻辑也就是说我们生成的动态代理类的同名方法是通过实现前置逻辑和后置逻辑被代理类的同名方法来实现动态代理这样既不会丢失原本逻辑也可以做大增强
【4】在main方法中
proxy.save()这个方法其实即是动态代理生成的方法也就是MyInvocationHandler中的invoke方法
图解逻辑 CGLIB
CGLIB是非官方创建的动态代理库。它通过继承被代理类来创建代理类。CGLib不需要被代理类实现接口它能够代理普通的类。CGLib通过修改字节码来实现代理。
代码示例
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;// 被代理类
class RealSubject {public void doSomething() {System.out.println(RealSubject doSomething);}
}// 代理类
class ProxySubject implements MethodInterceptor {private Object target; // 被代理对象public Object getInstance(Object target) {this.target target;Enhancer enhancer new Enhancer();enhancer.setSuperclass(this.target.getClass());enhancer.setCallback(this);return enhancer.create();}public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println(Before method: method.getName());Object result proxy.invokeSuper(obj, args);System.out.println(After method: method.getName());return result;}
}public class CGLIBDynamicProxyExample {public static void main(String[] args) {ProxySubject proxy new ProxySubject();RealSubject realSubject (RealSubject) proxy.getInstance(new RealSubject());realSubject.doSomething();}
}【1】在这段代码中我们会发现在ProxySubject类中的getInstance方法也需要传入被代理类target但与JDK 不同的是这个方法内部是为了获取他的class类然后生成一个代理类继承自被代理类。
【2】与JDK Proxy中类似也有一个类似于invoke方法的intercept方法他内部执行的proxy.invokeSuper(obj,args)其实就是调用父类的目标方法也就是被代理类的方法
【3】在main方法中我们会发现其创建代理类的方式和JDK Proxy很相似都需要把代理规则类放入到代理工厂中进行创建最后创建出来的对象就是被代理对象的子类
图解 仅为个人学习笔记 感谢阅读