学习Java——代理
目录
静态代理
动态代理
动态代理的几种实现方式
Java实现动态代理的大致步骤
Java 实现动态代理主要涉及哪几个类
动态代理实现
jdk动态代理
cglib动态代理
AOP
每日寄语
静态代理
所谓静态代理,就是代理类是由程序员自己编写的,在编译期就确定好了的。来看下下面的例子:
public interface HelloSerivice {public void say();
}public class HelloSeriviceImpl implements HelloSerivice{@Overridepublic void say() {System.out.println("hello world");}
}
上面的代码比较简单,定义了一个接口和其实现类。这就是代理模式中的目标对象和目标对象的接口。接下来定义代理对象。
public class HelloSeriviceProxy implements HelloSerivice{private HelloSerivice target;public HelloSeriviceProxy(HelloSerivice target) {this.target = target;}@Overridepublic void say() {System.out.println("记录日志");target.say();System.out.println("清理数据");}
}
上面就是一个代理类,他也实现了目标对象的接口,并且扩展了say方法。下面是一个测试类:
public class Main {@Testpublic void testProxy(){//目标对象HelloSerivice target = new HelloSeriviceImpl();//代理对象HelloSeriviceProxy proxy = new HelloSeriviceProxy(target);proxy.say();}
}
这就是一个简单的静态的代理模式的实现。代理模式中的所有角色(代理对象、目标对象、目标对象的接口)等都是在编译期就确定好的。
静态代理的用途
1.控制真实对象的访问权限:通过代理对象控制真实对象的使用权限。
2.避免创建大对象:通过使用一个代理小对象来代表一个真实的大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
3.增强真实对象的功能:这个比较简单,通过代理可以在调用真实对象的方法的前后增加额外功能。
动态代理
前面介绍了静态代理,虽然静态代理模式很好用,但是静态代理还是存在一些局限性的,比如使用静态代理模式需要程序员手写很多代码,这个过程是比较浪费时间和精力的。一旦需要代理的类中方法比较多,或者需要同时代理多个对象的时候,这无疑会增加很大的复杂度。
有没有一种方法,可以不需要程序员自己手写代理类呢。这就是动态代理啦。
动态代理中的代理类并不要求在编译期就确定,而是可以在运行期动态生成,从而实现对目标对象的代理功能。
反射是动态代理的一种实现方式。
动态代理的几种实现方式
Java中,实现动态代理有两种方式:
1、JDK动态代理:java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。
2、Cglib动态代理:Cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。
关于这两种动态代理的写法本文就不深入展开了,读者感兴趣的话,后面我再写文章单独介绍。本文主要来简单说一下这两种动态代理的区别和用途。
JDK动态代理和Cglib动态代理的区别
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
Cglib包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它需要你对JVM内部结构包括class文件的格式和指令集都很熟悉。
Cglib与动态代理最大的区别就是:
使用动态代理的对象必须实现一个或多个接口
使用cglib代理的对象则无需实现接口,达到代理类无侵入。
Java实现动态代理的大致步骤
1、定义一个委托类和公共接口。
2、自己定义一个类(调用处理器类,即实现 InvocationHandler 接口),这个类的目的是指定运行时将生成的代理类需要完成的具体任务(包括Preprocess和Postprocess),即代理类调用任何方法都会经过这个调用处理器类(在本文最后一节对此进行解释)。
3、生成代理对象(当然也会生成代理类),需要为他指定(1)委托对象(2)实现的一系列接口(3)调用处理器类的实例。因此可以看出一个代理对象对应一个委托对象,对应一个调用处理器实例。
Java 实现动态代理主要涉及哪几个类
java.lang.reflect.Proxy: 这是生成代理类的主类,通过 Proxy 类生成的代理类都继承了 Proxy 类,即 DynamicProxyClass extends Proxy。
java.lang.reflect.InvocationHandler: 这里称他为"调用处理器",他是一个接口,我们动态生成的代理类需要完成的具体内容需要自己定义一个类,而这个类必须实现 InvocationHandler 接口。
动态代理实现
使用动态代理实现功能:不改变Test类的情况下,在方法target 之前打印一句话,之后打印一句话。
public class UserServiceImpl implements UserService {@Overridepublic void add() {// TODO Auto-generated method stubSystem.out.println("--------------------add----------------------");}
}
jdk动态代理
public class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {super();this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {PerformanceMonior.begin(target.getClass().getName()+"."+method.getName());//System.out.println("-----------------begin "+method.getName()+"-----------------");Object result = method.invoke(target, args);//System.out.println("-----------------end "+method.getName()+"-----------------");PerformanceMonior.end();return result;}public Object getProxy(){return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);}}public static void main(String[] args) {UserService service = new UserServiceImpl();MyInvocationHandler handler = new MyInvocationHandler(service);UserService proxy = (UserService) handler.getProxy();proxy.add();
}
cglib动态代理
public class CglibProxy implements MethodInterceptor{ private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz){ //设置需要创建子类的类 enhancer.setSuperclass(clazz); enhancer.setCallback(this); //通过字节码技术动态创建子类实例 return enhancer.create(); } //实现MethodInterceptor接口方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("前置代理"); //通过代理类调用父类中的方法 Object result = proxy.invokeSuper(obj, args); System.out.println("后置代理"); return result; }
} public class DoCGLib { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); //通过生成子类的方式创建代理类 UserServiceImpl proxyImp = (UserServiceImpl)proxy.getProxy(UserServiceImpl.class); proxyImp.add(); }
}
AOP
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。
如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
关于代理,之前我也总结过相关博客,链接放在下面,有兴趣的可以学习参考:
java——代理_别活在过去i的博客-CSDN博客
cglib动态代理_别活在过去i的博客-CSDN博客
了解一下Spring AOP_别活在过去i的博客-CSDN博客
每日寄语
人这一辈子千万不要马虎做两件事:一是找对事业,二是找对爱人,因为太阳升起时要投身事业,太阳落下时要与爱人相拥,我们终其一生都在寻找两样东西,一是价值感二是归属感。价值感来源于肯定,归属感来源于被爱。人要有日出时的自豪感也要享受日落时的相拥——葛优
学习Java——代理相关推荐
- Java架构师笔记-你必须掌握学习Java需要掌握哪些技能
闲来无事,师长一向不(没)喜(有)欢(钱)凑热闹,倒不如趁着这时候复盘复盘.而写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,希望可以给大家一些经验,能让大家更好学习和使用Jav ...
- 简单的介绍一下怎样如何学习Java基础
在我看来,学习Java最好的方式就是通过书籍(或博客)+动手写代码,辅以视频,通过多写多练,达到熟练掌握的程度.博主曾经看过一篇文章,讲的是费曼学习法,其中讲到学习的四个步骤:选择目标.教学.纠错学习 ...
- 设计模式学习之代理模式学习(一)
设计模式学习之代理模式学习(一) 关于设计模式想必学习过Java语言的人都知道吧,当时对其进行深入学习的的人应该不是很多.在我看来设计方面的知识相比于框架应用配置等知识要有意思的多,并且设计模式的对一 ...
- 通过 Lotus Domino Java 代理消费 Web 服务
Web 服务是一种允许两台或更多的计算机在网络中交互的系统设计.这种服务的主要优点是,它是在多台不同操作系统的计算机和应用服务器之间发送对象的标准解决方法.例如,我们的公司使用 Web 服务从一台运行 ...
- java编程学习方法_在线学习Java编程的最佳方法
java编程学习方法 1.简介 Java是使用最广泛的编程语言之一. 根据Github的最新报告 ,Java被列为仅次于JavaScript的第二大最常用的编程语言. 掌握Java的人有很多话题. 好 ...
- java编写代理服务器_如何编写Java代理
java编写代理服务器 对于vmlens (轻量级Java竞争条件捕获器),我们使用Java代理来跟踪字段访问. 这是我们学习的实现此类代理的经验教训. 开始 使用"静态公共静态无效值pre ...
- 在线学习Java编程的最佳方法
1.简介 Java是使用最广泛的编程语言之一. 根据Github的最新报告 ,Java被列为仅次于JavaScript的第二大最常用的编程语言. 掌握Java的人有很多话题. 好消息是,您可以在线找到 ...
- 如何编写Java代理
对于vmlens (轻量级Java竞争条件捕获器),我们使用Java代理来跟踪字段访问. 这是我们学习的实现此类代理的经验教训. 开始 使用" static public static vo ...
- 学习 Java 的历程和体会『写给新手看,欢迎老司机批评和建议』
转载出处:https://blog.csdn.net/lw_power/article/details/52502698#commentBox Java 基础只能说熟悉,还达不到熟练,更谈不上精通.框 ...
最新文章
- CCS下DSP仿真实现双边带调制与频谱分析(查表法)
- http://www.csdn.net/
- SAP UI5 batch 请求的响应解析流程分析
- 线性求逆元模板_算法学习笔记(9):逆元
- How to remove ROM in MAME
- LanguageTool性能简单测试分析
- python无法启动此程序因为_python报错:无法启动此程序,因为计算机中丢失
- 华为、中兴嵌入式(C)笔试题
- 25.龙贝格求积公式
- VMware Guided Consolidation
- 小程序开发用什么编程语言_微信小程序开发教程是什么?费用多少?
- Matlab扫雷记录01-matlab中获得向量非零元素个数
- 使用windows时卸载office,后想恢复原来的office
- CMake中file的使用
- 数学建模系列-预测模型(六)---微分方程模型
- WINDOWS服务器性能监控器的监视以及邮件预警配置
- 运放-1-理想运放与虚断虚短的来源
- 绘制帧率与实际显示时帧率不同步,怎么测得显示帧率?
- 常见二叉树定义及其性质
- 日本“茑屋书店”营销模式的一点见解