(十七)关于动态代理,你能说出动态代理的几种方式?

简介: 动态代理是指代理类不是写在代码中的,而是在代码运行过程中产生的,Java提供了两种方式来实现动态代理,分别是基于Jdk的动态代理和基于Cglib的动态代理。

微信搜索《Java鱼仔》,每天一个知识点不错过


(一)每天一个知识点


关于动态代理,你能说出动态代理的几种方式?


(二)详解


动态代理是指代理类不是写在代码中的,而是在代码运行过程中产生的,Java提供了两种方式来实现动态代理,分别是基于Jdk的动态代理和基于Cglib的动态代理。


2.1 基于Jdk的动态代理


首先我们来搭建一套实现动态代理的实现,以租房为例,我新建一个租房的接口:


publicinterfaceRoom {
voidrent();
}

然后下一个实际的租房实现类


publicclassRealRoomimplementsRoom {
privateStringroomname;
publicRealRoom(Stringroomname) {
this.roomname=roomname;
    }
publicvoidrent() {
System.out.println("租了"+roomname);
    }
}

基于Jdk的动态代理核心在于InvocationHandler 接口,首先我们新建一个类ProxyHandler来实现这个InvocationHandler 接口,并实现里面的invoke方法


publicclassProxyHandlerimplementsInvocationHandler {
Objectobject;
publicProxyHandler(Objectobject) {
this.object=object;
    }
//proxy 代理对象//method 要实现的方法//args 方法的参数    publicObjectinvoke(Objectproxy, Methodmethod, Object[] args) throwsThrowable {
System.out.println("代理执行之前:"+method.getName());
Objectinvoke=method.invoke(object, args);
System.out.println("代理执行之后:"+method.getName());
returninvoke;
    }
}

InvocationHandler 是一个接口,每个代理的实例都有一个与之关联的

InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类invoke,由它实现处理内容。


接下来写一个方法来实现动态代理


publicstaticvoidmain(String[] args) {
Roomroom=newRealRoom("碧桂园");
//obj.getClass().getClassLoader()类加载器//obj.getClass().getInterfaces() 目标类实现的接口//InvocationHandler对象InvocationHandlerinvocationHandler=newProxyHandler(room);
RoomproxyRoom= (Room) Proxy.newProxyInstance(room.getClass().getClassLoader(), room.getClass().getInterfaces(), invocationHandler);
proxyRoom.rent();
}

这段代码的另外一个核心是Proxy.newProxyInstance,该方法需要三个参数,目的是运行期间生成代理类,每个参数的功能已经写在了注释中。这段代码的意思就是Proxy 动态产生的代理对象会调用 InvocationHandler 实现类invoke。


最终我们不需要RealRoom去调用rent方法,通过代理类就可以实现这个rent方法。


最后结果如下:


代理执行之前:rent租了碧桂园代理执行之后:rent

运行时就会在控制台上打印出来,这也是Spring AOP的核心


JDK动态代理类实现了InvocationHandler接口,重写的invoke方法。


JDK动态代理的基础是反射机制(method.invoke(对象,参数))


Proxy.newProxyInstance()


2.2 基于Cglib的动态代理


基于Jdk的动态代理局限性在于代理的类必须要实现接口,而基于CGlib的动态代理则没有这个限制:


搭建CGlib环境我们首先要引入一个CGlib的jar包:



<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version></dependency>

此时我们不再需要接口,直接新建一个CGRoom类:


publicclassCGRoom {
publicvoidrent(StringroomName){
System.out.println("租了"+roomName);
    }
}

CGlib实现动态代理的核心在于MethodInterceptor接口:


publicclassMyMethodInterceptorimplementsMethodInterceptor {
@OverridepublicObjectintercept(Objecto, Methodmethod, Object[] objects, MethodProxymethodProxy) throwsThrowable {
System.out.println("代理执行之前:"+method.getName());
Objectobject=methodProxy.invokeSuper(o,objects);
System.out.println("代理执行之后:"+method.getName());
returnobject;
    }

这个接口只有一个intercept()方法,拦截被代理对象,这个方法有4个参数:


1)表示增强的对象,即实现这个接口类的一个对象;


2)表示要被拦截的方法;


3)表示要被拦截方法的参数;


4)表示要触发父类的方法对象;


最后生成代理类对象并输出执行结果


publicstaticvoidmain(String[] args) {
//创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数Enhancerenhancer=newEnhancer();
//设置目标类的字节码文件enhancer.setSuperclass(CGRoom.class);
//设置回调函数enhancer.setCallback(newMyMethodInterceptor());
//创建代理对象CGRoomproxy= (CGRoom) enhancer.create();
proxy.rent("碧桂园");
}

运行结果:


代理执行之前:rent租了碧桂园代理执行之后:rent


(三)总结


两种代理方式各有优劣,在使用方面,JDK动态代理只能基于接口进行实现,而CGLIb对代理的目标对象无限制,无需实现接口。


在依赖方面,Java原生支持JDK动态代理,而CGlib的实现还需要引入相关依赖包。

相关文章
|
1月前
|
Java
【编程进阶知识】静态代理、JDK动态代理及Cglib动态代理各自存在的缺点及代码示例
本文介绍了三种Java代理模式:静态代理、JDK动态代理和Cglib动态代理。静态代理针对特定接口或对象,需手动编码实现;JDK动态代理通过反射机制实现,适用于所有接口;Cglib动态代理则基于字节码技术,无需接口支持,但需引入外部库。每种方法各有优缺点,选择时应根据具体需求考虑。
20 1
|
3月前
|
设计模式 Java 中间件
静态代理和动态代理的区别以及实现过程
这篇文章通过示例代码讲解了静态代理和动态代理在Java中的使用方式和区别,重点介绍了动态代理的实现原理及其在Spring框架中的应用。
静态代理和动态代理的区别以及实现过程
|
6月前
|
JSON 前端开发 Java
数据映射框架之三大神器:反射、注解、动态代理
数据映射框架之三大神器:反射、注解、动态代理
56 3
数据映射框架之三大神器:反射、注解、动态代理
|
设计模式 Java 数据安全/隐私保护
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理) 1
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理)
86 0
|
6月前
|
Java 开发者 Spring
什么是静态代理和动态代理,两者的区别(笔记)
什么是静态代理和动态代理,两者的区别(笔记)
206 0
|
Java
十五 Java反射机制
十五 Java反射机制
39 0
|
设计模式 Java Maven
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理) 2
设计模式之代理模式(jdk和cglib、手撕源码、自创动态代理)
56 0
|
Java
动态代理学习(一)自己动手模拟JDK动态代理
动态代理学习(一)自己动手模拟JDK动态代理
98 0
动态代理学习(一)自己动手模拟JDK动态代理
|
缓存 Java
源码阅读 | 动态代理
源码阅读 | 动态代理
|
存储 设计模式 缓存
一直在使用JDK动态代理, 不明白原理如何实现?
一直在使用JDK动态代理, 不明白原理如何实现?
一直在使用JDK动态代理, 不明白原理如何实现?