JAVA代理模式-cglib动态代理的实现(三)
传送门:JAVA代理模式-静态代理的实现(一)
JAVA代理模式-JDK动态代理的实现(二)
JAVA代理模式-cglib动态代理的实现(三)
JAVA代理模式-三种代理模式的对比(四)
代理模式简介、静态代理、JDK动态代理可以参考以下文章:
JAVA代理模式-静态代理的实现(一)
JAVA代理模式-JDK动态代理的实现(二)
CGLIB动态代理:
在之前JAVA代理模式-静态代理的实现(一)和 JAVA代理模式-JDK动态代理的实现(二)中,实现代理模式时,首先需要定义一个接口,然后定义实现该接口的实现类,以及获得实现该接口的代理类。
但是如果没有定义接口,只定义了实体类。很显然JDK代理是无法使用了,因为JDK动态代理要求必须定义接口,对接口进行代理。这时,我们就可以使用CGLIB动态代理来实现。
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。但是使用CGLIB需要自行进行导包。
考虑以下场景,你需要去中介手里买电影票,中介会在售票的基础上增强手续费。
则电影院为真实主题类,而中介则为代理类,在真实主题类售卖电影票的基础上,增强功能收取了一定的手续费。
导包
1.使用了Maven管理项目则引入一下坐标即可。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
2.未使用maven,则可以通过如下方式导包。
参考链接:在文章的后半部分,有下载和导入的方式
在完成环境配置之后,进行CGLIB动态代理的实现:
1.编写实体类。即被代理类,该类并不需要实现接口。
public class NbCinema {
public void sell(String type){
System.out.println("售卖火车票!" + "("+type+")");
}
}
2.通过cglib动态生成代理类,动态生成的代理类为实体类的子类。
新建工厂类,即CglibProxyFactory,该工厂就是用来获取代理对象的,所以我们应该在该工厂类中定义一个获取代理对象的方法,此时,使用CGLIB进行代理的话,获得的代理类就是目标对象所属类的子类。
使用CGLIB来进行代理流程如下:
- 创建Enhancer类对象,该类类似于JDK动态代理中的Proxy类。它就是用来获取代理对象的。
- 设置父类的字节码对象。使用CGLIB生成的代理类是属于目标类的子类的,也就是说代理类是要继承自目标类的。
- 设置回调函数。
public class CglibProxyFactory<T> implements MethodInterceptor {
private T obj;
public CglibProxyFactory(T obj){
this.obj = obj;
}
public T getProxyObject(){
// 创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
Enhancer enhancer = new Enhancer();
// 设置父类的字节码对象,
enhancer.setSuperclass(obj.getClass());
// 设置回调函数
enhancer.setCallback(this);
// 创建代理对象
T o = (T) enhancer.create(); // 生成的代理对象,为NbCinema类的子类
return o;
}
/*
intercept方法参数说明:
o : 代理对象
method : 真实对象中的方法的Method实例
args : 实际参数
methodProxy :代理对象中的方法的method实例
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("收费500");
//1.生成的代理对象是实际对象的子类,所以这里调用Super方法,即父类的sell方法。
// Object invoke = methodProxy.invokeSuper(o, args);
//2.或者还可以使用被代理对象直接进行调用
Object invoke = method.invoke(obj, args);
System.out.println("购票成功!!!");
return invoke;
}
}
3. 客户端从中介买票
public class CglibProxyTest {
public static void main(String[] args) {
NbCinema nbc = new NbCinema();
CglibProxyFactory gcp = new CglibProxyFactory<NbCinema>(nbc);
NbCinema nbc_proxy = (NbCinema) gcp.getProxyObject();
// 执行sell方法时,会回调函数
// public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
// 进行执行
nbc_proxy.sell("二等座");
}
}
CGLIB实现动态代理的完整代码:
package com.csdn.proxy.cglibproxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class NbCinema {
public void sell(String type){
System.out.println("售卖火车票!" + "("+type+")");
}
}
public class CglibProxyFactory<T> implements MethodInterceptor {
private T obj;
public CglibProxyFactory(T obj){
this.obj = obj;
}
public T getProxyObject(){
// 创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
Enhancer enhancer = new Enhancer();
// 设置父类的字节码对象,
enhancer.setSuperclass(obj.getClass());
// 设置回调函数
enhancer.setCallback(this);
// 创建代理对象
T o = (T) enhancer.create(); // 生成的代理对象,为NbCinema类的子类
return o;
}
/*
intercept方法参数说明:
o : 代理对象
method : 真实对象中的方法的Method实例
args : 实际参数
methodProxy :代理对象中的方法的method实例
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("收费500");
//1.生成的代理对象是实际对象的子类,所以这里调用Super方法,即父类的sell方法。
// Object invoke = methodProxy.invokeSuper(o, args);
//2.或者还可以使用被代理对象直接进行调用
Object invoke = method.invoke(obj, args);
System.out.println("购票成功!!!");
return invoke;
}
}
public class CglibProxyTest {
public static void main(String[] args) {
NbCinema nbc = new NbCinema();
CglibProxyFactory gcp = new CglibProxyFactory<NbCinema>(nbc);
NbCinema nbc_proxy = (NbCinema) gcp.getProxyObject();
// 执行sell方法时,会回调函数
// public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
// 进行执行
nbc_proxy.sell("二等座");
}
}