一 前言
java中的代理模式主流的有三种,分别是静态代理模式,cglib代理模式和java原生的代理模式;要学习cglib动态代理和java原生代理必须要掌握静态代理模式,地基是架起高楼大厦的基石;
二 静态代理模式
2.1 静态代理介绍
代理模式的定义是提供一个代理对象用来控制对这个对象的访问;我们以具体的例子说明静态代理模式:抽象类person中有个购物的方法,主体类zxzxz(知识追寻者)实现了person类,方法主体是想去澳洲购买大米,zxzxz在中国啊离澳洲很远,去一趟澳洲买东西成本太高了,不太现实。于是zxzxz在网上找了个去澳洲购物的代理(proxy)也实现了person的购物方法,帮zxzxz去澳洲买东西,然后zxzxz就可以用很低的代价获得澳洲的大米,本人还不用去澳洲,感觉很好对吧;
2.2 抽象类person
person接口中有一个抽象方法就是购物;
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/11/20 17:00
*/
public interface Person {
// 人的购买方法
public String shop();
}
2.3 主体类zxzxz
主体类也就是代理的目标对象,其是被真正执行的主体;主体类实现了接口person,并重写了购物方法;
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/11/20 17:02
*/
public class ZXZXZ implements Person {
@Override
public String shop() {
return "去澳洲买大米";
}
}
2.4 代理对象proxy
代理对象proxy也实现了person接口,但是其重写的购物方法的主体内容不是自己的,而是直接调用了主体类的购物方法;
/**
* @Author lsc
* @Description <p>代理对象 </p>
* @Date 2019/11/20 17:03
*/
public class Proxy implements Person {
// 知识追寻者
private ZXZXZ zxzxz;
// 代理的购买方法
@Override
public String shop() {
// 对象为空则创建
if (zxzxz==null){
zxzxz = new ZXZXZ();
}
// 调用知识追寻者的购买方法
return zxzxz.shop();
}
}
2.5 代理模式测试
public static void main(String[] args) {
// 创建代理对象
Proxy proxy = new Proxy();
// 调用代理对象的购买方法,实际上是zxzxz的购买方法
String shop = proxy.shop();
// 去澳洲买大米
System.out.println(shop);
}
三 jdk动态代理
3.1 jdk动态代理介绍
jdk动态代理对象主要通过 java.lang.reflect.Proxy
,java.lang.reflect.InvocationHandler
2个类实现动态代理;Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
有三个参数分别是
ClassLoader
(被代理对象的类加载器);interfaces
被代理对象的接口类型,即将被代理对象绑定到那些接口下;InvocationHandler
(事件处理器)是java.lang.reflect.InvocationHandler
接口里面只有一个invoke(Object proxy, Method method, Object[] args)
的抽象方法,我们需要重写invoke
方法
3.1 抽象类person
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/11/20 17:00
*/
public interface Person {
// 人的购买方法
public String shop();
}
3.2 目标对象ZXZXZ
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/11/20 17:02
*/
public class ZXZXZ implements Person {
@Override
public String shop() {
return "去澳洲买大米";
}
}
3.3 动态代理对象
/**
* @Author lsc
* @Description <p> java生成的代理</p>
* @Date 2019/11/20 20:01
*/
public class JProxy {
// 被代理的对象
private Object target;
// 构造器 提供被代理的对象
public JProxy(Object target){
this.target = target;
}
// 进行动态代理
public Object getProxyInstance(){
// 1获得类加载器
ClassLoader classLoader = target.getClass().getClassLoader();
// 2被代理对象的接口类型
Class<?>[] interfaces = target.getClass().getInterfaces();
// 3事件触发,将被代理的对象的方法做为参数传入
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 执行被代理对象的方法
Object invoke = method.invoke(target, args);
return invoke;
}
};
// 获得代理对象
Object instance = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
return instance;
}
}
3.3 jdk动态代理测试
public static void main(String[] args) {
// 创建被代理对象
Person person = new ZXZXZ();
// 创建代理对象
JProxy jProxy = new JProxy(person);
// 获得代理对象的实例
Person proxyInstance = (Person)jProxy.getProxyInstance();
// 调用代理对象的方法,实际上是被代理对象的方法
String shop = proxyInstance.shop();
// 去澳洲买大米
System.out.println(shop);
}
四 cglib动态代理
4.1 cglib动态代理介绍
cglib动态代理基于ASM的字节码生成库,允许在运行时形成代理,是一种子类代理;
cglib动态代理不像静态代理和jdk动态代理,其无需实现任何接口即可代理;cglib动态代理无法代理final修饰的类,其是外来物种,需要引入依赖;
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
</dependencies>
4.2 被代理对象
/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/11/20 17:02
*/
public class ZXZXZ {
public String shop() {
return "去澳洲买大米";
}
}
4.3 代理对象
/**
* @Author lsc
* @Description <p>cglib动态代理 </p>
* @Date 2019/11/20 21:57
*/
public class CglibProxy implements MethodInterceptor {
// 被代理的对象
private Object target;
// 构造器 提供被代理的对象
public CglibProxy(Object target){
this.target = target;
}
public Object getCglibProxyInstance(){
// 创建实例化工具
Enhancer enhancer = new Enhancer();
// 设置父类对象
enhancer.setSuperclass(this.target.getClass());
// 设置回调函数
enhancer.setCallback(this);
// 创建子类即被代理的对象
return enhancer.create();
}
/*
* @Author lsc
* @Description <p> </p>
* @Date 2019/11/20 22:03
* @Param [被增强的对象, 要拦截的方法, 参数列表, 对方法进行代理]
* @Return java.lang.Object
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 执行被代理对象的方法
Object invoke = method.invoke(target, objects);
return invoke;
}
}
4.4 cglib动态代理测试
public static void main(String[] args) {
// 创建被代理对象
ZXZXZ zxzxz = new ZXZXZ();
// 创建代理对象
CglibProxy cglibProxy = new CglibProxy(zxzxz);
// 获得代理对象的实例
ZXZXZ cglibProxyInstance = (ZXZXZ)cglibProxy.getCglibProxyInstance();
// 调用代理对象的方法,实际上是被代理对象的方法
String shop = cglibProxyInstance.shop();
// 去澳洲买大米
System.out.println(shop);
}
五 支持作者
点赞加关注,谢谢;