玩转JAVA代理模式
Posted 我想月薪过万
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玩转JAVA代理模式相关的知识,希望对你有一定的参考价值。
概念剖析
代理模式 是指为其他对象提供一种代理,以控制对这个对象的访问,代理对象在 客户端和目标对象 之间起到中介作用,属于结构型设计模式。
应用场景
该 设计模式 灵活的运用在 spring 的AOP(面向切片编程)中。
模式分类
静态代理、动态代理
实例演示
静态代理
场景描述:《相亲》张三有个找媳妇的需求,于是他找到了媒婆,媒婆就去物色美女满足张三的需求。
从上面这个场景中,我们可以看到:媒婆和张三 有一个共性都是人并且都有找美女的需求。所以,我们创建一个人的接口,一个张三类和一个媒婆类。
IPerson 接口
package proxy;
/**
* ClassName: IPerson <br/>
* Description: <br/>
* date: 2021/7/9 17:37<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public interface IPerson {
void findBeauty();
}
张三 类
package proxy;
/**
* ClassName: ZhangSan <br/>
* Description: <br/>
* date: 2021/7/9 17:40<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public class ZhangSan implements IPerson{
@Override
public void findBeauty() {
System.out.println("相亲要求:皮肤白,大长腿");
}
}
媒婆 类
package proxy;
/**
* ClassName: MeiPo <br/>
* Description: <br/>
* date: 2021/7/9 17:42<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public class MeiPo implements IPerson{
private ZhangSan zhangSan;
public MeiPo(ZhangSan zhangSan) {
this.zhangSan = zhangSan;
}
@Override
public void findBeauty() {
System.out.println("走遍世界,寻找美女");
zhangSan.findBeauty();
System.out.println("如期交货");
}
}
测试代码
package proxy;
/**
* ClassName: Main <br/>
* Description: <br/>
* date: 2021/7/9 21:21<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public class Main {
public static void main(String[] args) {
MeiPo meiPo = new MeiPo(new ZhangSan());
meiPo.findBeauty();
}
}
运行效果
善于思考的同学会发现这个存在一个弊端,那就是 这个媒婆代理存在局限性,只能为张三服务,这样肯定是不行滴,所以,出现了下面的动态代理。
动态代理
动态代理,就是动态创建代码在JVM虚拟机内存中跑,这个类是动态创建的,只存在于JVM内存中,不存在于实际。
实现方式:jdk库或cglib库
代码示例
人类 接口
package jdkProxy;
/**
* ClassName: IPenson <br/>
* Description: <br/>
* date: 2021/7/10 10:04<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public interface IPenson {
void findBeauty();
}
媒婆代理 类
package jdkProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* ClassName: JDKMeiPo <br/>
* Description: <br/>
* date: 2021/7/10 10:12<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public class JDKMeiPo implements InvocationHandler {
//第二步:存储需要代理的对象,方便第三步使用
private Object mTarget;
//第一步:获取动态创建的实例对象
public Object getInstance(Object target){
mTarget = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//第三步:执行被调用的方法
before();
method.invoke(mTarget,args);
after();
return null;
}
private void after() {
System.out.println("如期交货");
}
private void before() {
System.out.println("走遍世界,寻找美女");
}
}
张三 类
package jdkProxy;
/**
* ClassName: ZhangSan <br/>
* Description: <br/>
* date: 2021/7/10 10:20<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public class ZhangSan implements IPenson{
@Override
public void findBeauty() {
System.out.println("相亲要求:皮肤白,大长腿");
}
}
测试类
package jdkProxy;
/**
* ClassName: test <br/>
* Description: <br/>
* date: 2021/7/10 10:19<br/>
*
* @author yiqi<br />
* @since JDK 1.8
*/
public class test {
public static void main(String[] args) {
//第一步:创建代理
JDKMeiPo jdkMeiPo = new JDKMeiPo();
//第二步:获取动态创建的实体类 ,注意 这个实体类是动态创建的,已经不是张三了
IPenson penson = (IPenson) jdkMeiPo.getInstance(new ZhangSan());
//第三步:这个方法不是直接调用张三的 findBeauty() 方法,而是触发 invoke() 的调用
penson.findBeauty();
}
}
效果展示
如果大家领悟了上面动态代理的真谛,那么学习 cglib 就会非常简单,因为它都不用管你的接口,直接覆写类的所有方法,大家可以百度自行尝试。
文章链接:代理模式之 cglib
以上是关于玩转JAVA代理模式的主要内容,如果未能解决你的问题,请参考以下文章