
今日主题:代理模式的使用
主要内容:
1.代理模式的简单介绍
2.代理模式代码实现
下面进入正文~
1.代理模式介绍
1)代理模式定义
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用
2)为什么要使用代理模式
- 职责清晰:真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰
- 高扩展性:具体的角色随时都会变化,但是无论如何变化,都要实现相应的接口,而代理类这时候无需做任何变动
- 中介隔离作用:代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用
3)代理模式使用场景
- 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是在本机器中,也可是在另一台机器中。远程代理又叫做大使(Ambassador)。好处是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的对象是局域的而不是远程的,而代理对象承担了大部份的网络通讯工作。
- 虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。使用虚拟代理模式的好处就是代理对象可以在必要的时候才将被代理的对象加载;代理可以对加载的过程加以必要的优化。当一个模块的加载十分耗费资源的情况下,虚拟代理的好处就非常明显。
- Copy-on-Write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。
- 保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。保护代理的好处是它可以在运行时间对用户的有关权限进行检查,然后在核实后决定将调用传递给被代理的对象。
- Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
- 防火墙(Firewall)代理:保护目标,不让恶意用户接近。
- 同步化(Synchronization)代理:使几个用户能够同时使用同一个对象而没有冲突。
- 智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
4)spring中使用的代理模式
a.JDK自带的动态代理.
b.Spring框架自己提供的CGLIB的方式.
spring使用代理模式,主要是在AOP中体现,比如JdkDynamicApoProxy和Cglib2AopProxy;使用动态代理完成事务处理也是AOP的一种典型应用;其他的具体的通过Aop完成的功能这里就不详细描述了;
2.代理模式的实现
话不多说,直接上代码呗,所有代码中都有详细的代码注释,请仔细查看
代理模式实现图如下:

代理模式uml图
代理模式的实现方式主要有三种
- 静态代理
- JDK动态代理
- cglib代理模式。
静态代理模式很简单,分析一下动态代理和cglib代理,主要区别如下:
- 动态代理:jdk动态代理是通过jdk中的java.lang.reflect.Proxy类来实行的,底层的原理是根据接口和增强的方法,创建一个新类,所以必须基于接口
- cglib代理:是一个高性能开元的代码生成包,它的底层是通过ASM(一个小而快的字节码处理框架)来转换字节码,为一个类创建一个子类,然后对子类进行增强,解决jdk的无接口代理问题
代码实现方式如下,仅供参考,在实际的项目使用过程中,根据项目实际的进行代码结构变化
首先是通用接口如下:
/**
* @Author smile7up
* @createDate 2019-07-05
* @Description 接口类
*/
public interface ICoderService {
/**
* 编写代码部分
*/
void writeCode();
}
委托类如下:
/**
* @Author smile7up
* @createDate 2019-07-05
* @Description 委托类
*/
public class JavaCoderServiceImpl implements ICoderService {
@Override
public void writeCode() {
System.out.println("==java程序员需要写好多java代码==");
}
}
1.静态代理
静态代理代理类:
/**
* @Author smile7up
* @createDate 2019-07-05
* @Description 静态代理代理类
*/
public class JavaCoderLeaderServiceImpl implements ICoderService {
private ICoderService coder;
public JavaCoderLeaderServiceImpl(ICoderService coder) {
this.coder = coder;
}
@Override
public void writeCode() {
System.out.println("==静态代理:作为leader需要先做技术设计==");
coder.writeCode();
System.out.println("==静态代理:作为leader需要再做技术测试==");
}
}
静态代理测试类:
/**
* @Author smile7up
* @createDate 2019-07-05
* @Description 静态代理测试类
*/
public class CommonProxyTest {
public static void main(String[] args) {
//声明一个委托类
ICoderService coder= new JavaCoderServiceImpl();
//使用静态代理模式声明一个代理类
JavaCoderLeaderServiceImpl javaCoderLeader =new JavaCoderLeaderServiceImpl(coder);
//触发相应的方法
javaCoderLeader.writeCode();
}
}
测试结果如下:

2.jdk动态代理
动态代理工厂:
/**
* @Author smile7up
* @createDate 2019-07-07
* @Description 动态代理代理工厂
*/
public class DynamicCodeLeaderProxyFactory {
/**
* 维护一个目标对象
*/
private Object target;
public DynamicCodeLeaderProxyFactory(Object target){
this.target=target;
}
/**
* 给目标对象生成代理对象
* @return
*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(
//固定写法开始
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
//固定写法结束
//自行实现方法开始
//执行目标对象方法前 需要执行的
System.out.println("===动态代理:作为leader需要先做技术设计===");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
//执行目标对象方法后 需要执行的
System.out.println("==动态代理:作为leader需要再做技术测试==");
return returnValue;
}
);
}
}
动态代理模式测试类
/**
* @Author smile7up
* @createDate 2019-07-05
* @Description 动态代理测试类
*/
public class DynamicProxyTest {
public static void main(String[] args) {
//声明一个委托类
ICoderService coder= new JavaCoderServiceImpl();
//使用动态代理生成代理类
ICoderService coderService = (ICoderService) new DynamicCodeLeaderProxyFactory(coder).getProxyInstance();
//执行相应的方法
coderService.writeCode();
}
}
测试结果如下:

2.cglib代理
cglib代理工厂:
/**
* @Author smile7up
* @createDate 2019-07-08
* @Description cglib代理工厂
*/
public class CglibProxyFactory implements MethodInterceptor {
/**
* 目标对象
*/
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
/**
* 给目标对象创建一个代理对象(固定写法)
* @return
*/
public Object getProxyInstance() {
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//执行目标对象方法前需要执行的
System.out.println("===cglib代理:作为leader需要先做技术设计===");
//执行目标对象的方法
Object returnValue = method.invoke(target, args);
//执行目标对象方法后需要执行的
System.out.println("===cglib代理:作为leader需要先做技术设计===");
return returnValue;
}
}
cglib代理测试类
/**
* @Author smile7up
* @createDate 2019-07-06
* @Description cglib代理测试类
*/
public class CglibProxyTest {
public static void main(String[] args) {
//声明一个委托类
JavaCoderServiceImpl coder= new JavaCoderServiceImpl();
//使用cglib声明一个代理类
JavaCoderServiceImpl leaderCoder= (JavaCoderServiceImpl)new CglibProxyFactory(coder).getProxyInstance();
//执行方法
leaderCoder.writeCode();
}
测试结果如下:

如每个测试结果一样,每种都实现了相应的代理方式
接下来主要是对常见的设计模式进行分享,jvm知识进行分享,大致的分享流程如下,这样可以有个系统性的分享,不至于时间太过碎片化,无法形成知识体系,下图会进行持续的更新

想获取实时的学习资料吗?打开微信,搜索公众号程序员地铁时光,获取最新技术知识
