关于代理。谢谢方志朋
Java 代理模式
什么是代理
代理是一种设计模式,它的核心思想,是将对目标的访问转移到代理对象上。这样做的好处就是,目标对象在不改变代码的情况下,可以通过代理对象加一些额外的功能。这是一种编程思想,在不改变原有代码的情况下,通过代理增加一些扩展功能。
代理过程如图所示,用户访问代理对象,代理对象通过访问目标对象,来达到用户访问目标对象的目的,
代理模式包含一下三个角色:
ISubject:接口对象,该接口是对象和它的代理共用的接口。
TargetSubject:目标对象,是实现抽象主题接口的类。
Proxy:代理角色,内部含有对目标对象TargetSubject的引用,从而可以操作真实对象。代理对象提供与目标对象相同的接口,以便在任何时刻都能代替目标对象。同时,代理对象可以在执行目标对象操作时,附加其他的操作,相当于对真实对象进行封装。
常见的代理模式分为静态代理和动态代理,动态代理在Java中的实现分为JDK动态代理和cglib代理。
静态代理
在之前已经说过,在代理模式中有三个角色,一是目标接口,二是目标对象,三是代理对象。
现在以具体代码来实现,首先是目标接口如下:
public interface IBlogService {void writeBlog();
}
目标对象实现了目标接口,代码如下:
public class BlogService implements IBlogService {@Overridepublic void writeBlog() {System.out.println("i'm writing...");}
}
静态代理对象,通过构造方法获取到目标对象,并实现了目标接口,在目标接口的方法里调用了目标对象的方法,代码如下:
public class BlogStaticProxy implements IBlogService{private IBlogService blogService;public BlogStaticProxy(IBlogService blogService) {this.blogService = blogService;}@Overridepublic void writeBlog() {System.out.println("start writing...");blogService.writeBlog();System.out.println("end writing...");}
}
测试:
public class TestStaticProxy {public static void main(String[] args) {IBlogService target = new BlogService();BlogStaticProxy proxy = new BlogStaticProxy(target);proxy.writeBlog();}
}
start writing…
i’m writing…
end writing…
静态代理,在不修改目标对象的情况下,可以通过代理对象做额外的扩展功能。但静态方法不是很灵活,如果目标接口的代码修改,目标对象和代理对象都需要修改。
动态代理在一定程度上避免这种情况,动态代理不需要代理对象实现目标接口,并且上在java 虚拟机的内存中动态的生成代理对象
Jdk动态对象
Jdk的动态代理由Proxy这个类来生成,它有三个参数:
ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{}
Jdk的动态代理代码如下:
public class JdkBlogProxyFactory {private Object target;public JdkBlogProxyFactory(Object target) {this.target = target;}public Object newInstance() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),(proxy, method, args) -> {System.out.println("start writing");Object o = method.invoke(target, args);System.out.println("end writing");return o;});}
}
测试类:
public class TestJdkProxy {public static void main(String[] args) {IBlogService target = new BlogService();System.out.println(target.getClass());// 给目标对象,创建代理对象IBlogService proxy = (IBlogService) new JdkBlogProxyFactory(target).newInstance();// class $Proxy0 内存中动态生成的代理对象System.out.println(proxy.getClass());// 执行方法 【代理对象】proxy.writeBlog();}
}
控制台打印如下:
class com.forezp.proxy.BlogService
class com.sun.proxy.$Proxy0
start writing
i'm writing...
end writing
CGLib动态代理
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
CglibBlogFactory代理工厂类如下:
public class CglibBlogFactory implements MethodInterceptor {private Object target;public CglibBlogFactory(Object target) {this.target = target;}//给目标对象创建一个代理对象public Object getProxyInstance() {//1.工具类Enhancer en = new Enhancer();//2.设置父类en.setSuperclass(target.getClass());//3.设置回调函数en.setCallback(this);//4.创建子类(代理对象)return en.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("start writing...");//执行目标对象的方法Object returnValue = method.invoke(target, objects);System.out.println("end writing...");return returnValue;}
}
测试类:
public class TestCglib {public static void main(String[] args) {IBlogService target = new BlogService();//代理对象IBlogService proxy = (IBlogService) new CglibBlogFactory(target).getProxyInstance();//执行代理对象的方法proxy.writeBlog();}
}
运行程序,控制台打印:
start writing...
i'm writing...
end writing...
参考资料
http://www.cnblogs.com/cenyu/p/6289209.html
http://blog.csdn.net/yakoo5/article/details/9099133/
关于代理。谢谢方志朋相关推荐
- Nginx配置反向代理,一篇搞定!
欢迎关注方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/zxd1435513775/article/ details/102508463 一.引言 其他话 ...
- 动态代理竟然如此简单!
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 这篇文章我们来聊一下 Java 中的动态代理. 动态代理在 ...
- nginx 反向代理和负载均衡策略实战案例
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:glmapper https://juejin.im/pos ...
- 懂点 Nginx 反向代理与负载均衡,是面试加分项没有之一
点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 学到老活到老 前端圈一直很新,一直要不停的学习,而且在进入大厂的路上,还要求熟悉一门后台语言等等 ...
- 企业服务内部接口校验方案
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:低调的码农 juejin.im/post/68449 ...
- 一位后端妹纸的面试总结(美团+阿里+携程+58+贝贝+招银+华为+....)
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:倾听潮汐 来源:nowcoder.com/discuss/5 ...
- 一套基础自动化部署搭建过程
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:LoyaltyLu segmentfault.com/a/1 ...
- SpringBoot+RabbitMQ ,保证消息100%投递成功并被消费(附源码)
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:rrd.me/f2cxz 一.先扔一张图 说明: 本文涵盖了 ...
- 淘宝服务端高并发分布式架构演进之路
点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 1. 概述 本文以淘宝作为例子,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时列 ...
- 最近面试 Java 后端开发的感受!
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 首发:cnblogs.com/JavaArchitect/p/10011253.html 上周,密 ...
最新文章
- lvm自动扩容到固定分区脚本
- RV1108开发环境搭建
- java数组创建后大小能改变吗,在Java中,数组创建成功以后,其大小(??? )(能/不能)改变...
- 难学的十大编程语言,C++位居第二,它才是第一名!
- 工行高级经理林承军:工行基于 MySQL 构建分布式架构的转型之路
- Spring:@AutoConfigurexxx注解-控制配置类的加载顺序
- java appt,(转从ajava)打开ppt
- 面向对象的设计原则-类设计原则
- a3图纸标题栏尺寸标准_求标准CAD图纸(A0、A1、A2、A3、A4)图框(外框、内框)、标题栏及明细栏大小样式字体是多大?...
- ir指令、立即数的作用_计算机系统概论-笔记
- 想转行学IT,Java怎么样?
- Oracle (03)分组子句.where条件 与 having条件的区别.子查询.DDL.DML.数据的增删改.TCL
- 【python初学者日记】输入年份:判断是否闰年:闰年:yyyy是闰年,这年有366天;yyyy是平年,这年有365天
- 从零开始搭建公司域环境(二):服务器安装域控并实现客户端加域登陆
- 【汇智学堂】基于Socket实现的网络版梅花易数一撮金游戏
- 一、Azure Kinect 传感器 SDK 下载——Azure Kinect DK入门
- sql登录名和用户名_通过分配角色和权限来移动或复制SQL登录名
- 因果推理(五):随机试验和可识别
- 硬件:宽带猫(光猫)的基础知识
- html网页宽度自动适应手机屏幕