代理类在程序运行时创建的代理方式被称为动态代理。 代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的指令动态生成的。 动态代理的优势在于可以很方便地对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。就 Java 来说,动态代理的实现方式,比如 JDK 动态代理、CGLIB 动态代理等。
在 Java 动态代理机制中 InvocationHandler 接口和 Proxy 类是核心。Proxy 类中使用频率最高的方法是:newProxyInstance() ,这个方法主要用来生成一个代理对象。
Proxy代理类
这个方法一共有 3 个参数:
loader :类加载器,用于加载代理对象。interfaces : 被代理类实现的一些接口;h : 实现了 InvocationHandler 接口的对象;要实现动态代理的话,还必须需要实现InvocationHandler接口 来自定义的处理逻辑。 当我们的动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。
InvocationHandler接口
invoke() 方法有下面三个参数:
proxy :动态生成的代理类method : 代理类对象调用的方法args : 代理调用的方法参数也就是说:你通过Proxy 类的 newProxyInstance() 创建代理对象的时候,实际会调用到实现InvocationHandler 接口的类的 invoke()方法。你可以在 invoke() 方法处理逻辑,通常是在前后加上逻辑。
定义短信接口:
public interface SmsService { String send(String message);}定义实现短信接口实现类:
public class SmsServiceImpl implements SmsService{ @Override public String send(String message) { System.out.println("send message:" + message); return message; }}定义JDK动态代理接口实现类:
import java.lang.reflect.Method;public class InvocationHandler implements java.lang.reflect.InvocationHandler { /** * 被代理的对象引用 */ private final Object target; public InvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method " + method.getName()); Object result = method.invoke(target, args); //调用方法之后,我们同样可以添加自己的操作 System.out.println("after method " + method.getName()); return result; }}最终是通过反射的invoke方法去调用被代理的方案的,因为动态执行的时候不知道具体是被调用哪个方法。
public class JDKProxy { public static void main(String[] args) { SmsService smsService = new SmsServiceImpl(); SmsService smsService2Proxy = (SmsService)Proxy.newProxyInstance( smsService.getClass().getClassLoader(), // 目标类的类加载 smsService.getClass().getInterfaces(), // 代理需要实现的接口,可指定多个 new InvocationHandler(smsService)); smsService2Proxy.send("send call") ; }}JDK动态代理执行的结果
CGLIB 动态代理类的使用步骤
在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。
你需要自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法。
net.sf.cglib.proxy.MethodInterceptor
obj :被代理的对象(需要增强的对象)method :被拦截的方法(需要增强的方法)args :方法入参methodProxy :用于调用原始方法通过 Enhancer类来动态获取被代理类,当代理类调用方法的时候,实际调用的是 MethodInterceptor 中的 intercept 方法。
CGLIB(Code Generation Library) 实际是属于一个开源项目,如果需要使用它的话,需要手动添加相关依赖。
cglib cglib 3.3.0 定义接口:
public interface SmsService { String send(String message);}定义接口实现类:
public class SmsServiceImpl implements SmsService{ @Override public String send(String message) { System.out.println("send message:" + message); return message; }}自定义方法拦截器:
import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable { //调用方法之前,我们可以添加自己的操作 System.out.println("before method " + method.getName()); Object object = proxy.invokeSuper( obj, args ); //调用方法之后,我们同样可以添加自己的操作 System.out.println("after method " + method.getName()); return object; }}最终使用:
import net.sf.cglib.proxy.Enhancer;public class CGLIBProxy { public static void main(String[] args) { // 创建动态代理增强类 Enhancer enhancer = new Enhancer(); Class clazz = SmsServiceImpl.class; // 设置类加载器 enhancer.setClassLoader(clazz.getClassLoader()); // 设置被代理类 enhancer.setSuperclass(clazz); // 设置方法拦截器 enhancer.setCallback(new MyMethodInterceptor()); // 创建代理类 SmsService smsService = (SmsService) enhancer.create(); smsService.send("send call") ; }}CGLIB代理输出
版权声明:我们致力于保护作者版权,注重分享,被刊用文章【java代理(JAVA动态代理详解)】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!;
工作时间:8:00-18:00
客服电话
电子邮件
beimuxi@protonmail.com
扫码二维码
获取最新动态
