java语言代理模式
来源:互联网 发布:淘宝运营正确思路流程 编辑:程序博客网 时间:2024/05/18 01:10
代理模式和JDK的动态代理技术学习笔记 01
一直对jdk的动态代理技术认识很模糊,花了几天时间研究它的实现原理。本文章涉及到累的加载以及java反射机制方面的知识。如果对这两方面有一定的理解
的话会更加容易明白。
代理模式:如果你学过或者知道装饰者模式,那么可以说你很容易就会掌握代理模式。
这两个模式很相似(个人的见解),都是通过传递一个需要被代理的对象(target)来
增强该类的功能。
代理模式的的本质就是传递一个目标对象(target)的引用来进行目标对象的本身具有的操作,但是同时
代理类会在执行目标对象(target)本身具有的方法之前和之后添加一些额外的操作,以达到增强目标对象
(target)功能的目的。
对于java语言来说,代理模式分为两种:1、静态代理;2、动态代理(目前主要包括JDK自身具备的动
态代理技术和cglib技术)
静态代理很好理解,下面结合代码来讲述:
先定义一个简单的接口:
代理模式:如果你学过或者知道装饰者模式,那么可以说你很容易就会掌握代理模式。
这两个模式很相似(个人的见解),都是通过传递一个需要被代理的对象(target)来
增强该类的功能。
代理模式的的本质就是传递一个目标对象(target)的引用来进行目标对象的本身具有的操作,但是同时
代理类会在执行目标对象(target)本身具有的方法之前和之后添加一些额外的操作,以达到增强目标对象
(target)功能的目的。
对于java语言来说,代理模式分为两种:1、静态代理;2、动态代理(目前主要包括JDK自身具备的动
态代理技术和cglib技术)
静态代理很好理解,下面结合代码来讲述:
先定义一个简单的接口:
package test.proxy; public interface BookFacade {//添加书本的方法void addBook(); }
然后就是这个接口的实现类:
package test.proxy; public class BookFacadeImpl implements BookFacade{@Overridepublic void addBook() {System.out.println("添加书本");} }
然后就是这个接口某个实现类的代理类:
package test.proxy; public class BookFacadeProxy { //目标类的一个引用private BookFacade target;public BookFacadeProxy(BookFacade target){ this.target=target;}public void addBook(){ System.out.println("==========添加操作之前========="); this.target.add(); System.out.println("==========添加操作之后=========");} }
然后就是测试了:
<pre name="code" class="java"><span style="font-size:18px;"> package test.proxy; public class Main{ BookFacade target=new BookFacadeImpl();BookFacadeProxy proxy=new BookFacadeProxy(target);proxy.addBook();} }</span>
执行测试之后的结果是:
==========添加操作之前=========
添加操作
==========添加操作之后=========
好了,这就是静态代理的一个基本应用。
接下来就是讲JDK的动态代理技术了。
动态代理技术主要是利用java.lang.reflect这个包的InvocationHandler接口和Proxy这两个类
先通过一个例子来演示动态代理的用法和效果
先定义一个接口:
动态代理技术主要是利用java.lang.reflect这个包的InvocationHandler接口和Proxy这两个类
先通过一个例子来演示动态代理的用法和效果
先定义一个接口:
package dynamic.proxy; /** * 目标对象实现的接口,用JDK来生成代理对象一定要实现一个接口 * @author zyb * @since 2012-8-9 * */ public interface UserService { /** * 目标方法 */ public abstract void add(); }
然后就是实现类:
package dynamic.proxy; /** * 目标对象 * @author zyb * @since 2012-8-9 * */ public class UserServiceImpl implements UserService { /* (non-Javadoc) * @see dynamic.proxy.UserService#add() */ public void add() { System.out.println("--------------------add---------------"); } }
接下来就是定义一个代理类:
package dynamic.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyProxy implements InvocationHandler{ //目标对象的引用 private UserService target; //构造方法传进一个UserService的实现类引用 public MyProxy(UserService target){ this.target=target; } //取得代理对象 public Object getMyProxy(){ return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(),this); } @Override /* proxy:代理类对象method:就是在这个参数所表示的方法的位置增强,和AOP思想中的横切点很相似(个人理解), 通过反射执行这个方法args:method执行所需要的参数。 */ public Object invoke(Object proxy,Method method,Object[] args) throws Exception{ //用于封装返回结果 Object result; System.out.println("======执行add方法之前============"); result = method.invoke(target,args); System.out.println("======执行add方法之后============"); return result; } }
然后就是测试了:
package dynamic.proxy;public class Main{public static void main(String[] args) throws Exception{//先声明一个目标对象 UserService target=new UserServiceImpl(); //取得代理对象 UserService proxy = (UserService)new MyProxy(target).getMyProxy(); //使用代理对象执行添加操作 proxy.add();} }
输出结果如下:
======执行add方法之前============
--------------------add---------------
======执行add方法之后============
好了,通过上面的例子可以知道动态代理对目标对象的add方法进行了增强操作。
但是从上面的例子也可以看出动态代理的局限性:需要和一个接口绑定在一起,只能针对
一类接口增强
其实可以将这个例子理解为一个简单的AOP实现。
值得注意的是proxy并没有显示的执行MyProxy类的invoke()方法。但是达到了增强操作。
了解下它背后进行的操作有助于我们更加好的动态代理技术,更好的运用它。
现在通过代码来探究这个过程:
将测试类Main改变下:
但是从上面的例子也可以看出动态代理的局限性:需要和一个接口绑定在一起,只能针对
一类接口增强
其实可以将这个例子理解为一个简单的AOP实现。
值得注意的是proxy并没有显示的执行MyProxy类的invoke()方法。但是达到了增强操作。
了解下它背后进行的操作有助于我们更加好的动态代理技术,更好的运用它。
现在通过代码来探究这个过程:
将测试类Main改变下:
package dynamic.proxy;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Main{public static void main(String[] args) throws Exception{//制定被代理的对象UserService target=new UserServiceImpl();//取得代理对象UserService proxy=(UserService) new MyProxy(target).getMyProxy(); //根据这里可以判断proxy是Proxy的子类,同时实现了UserService接口System.out.println(proxy instanceof Proxy);System.out.println(proxy instanceof UserService);System.out.println("==================================");//这里打印出这样的结果:proxy的类型是: class com.sun.proxy.$Proxy0 System.out.println("proxy的类型是: "+proxy.getClass().toString()); System.out.println("==================================="); //这里通过反射技术取得proxy这个对象的信息来分析下proxy的结构 Class clazz=proxy.getClass(); //属性 Field[] fields=clazz.getDeclaredFields(); System.out.println("proxy对象的属性有:"); for(Field f:fields){ System.out.println(f.getName()+" , "); } System.out.println("=================================="); //方法 Method[] method=clazz.getMethods(); System.out.println("proxy对象的方法有: "); for(Method m:method){ System.out.println(m.getName()+" , "); } System.out.println("==================================="); //父类 System.out.println("proxy的父类: "+clazz.getSuperclass()); System.out.println("===================================="); //接口 Class<?> interfaces[]=clazz.getInterfaces(); System.out.println("proxy实现的接口有: "); for(Class<?> i:interfaces){ System.out.println(i.getName()+" , "); } System.out.println("===================================="); //运行结果 System.out.println("运行结果: "); proxy.add(); } }
接下来是控制台输出的结果:
true
true
==================================
proxy的类型是: class com.sun.proxy.$Proxy0
===================================
proxy对象的属性有:
m1 ,
m3 ,
m0 ,
m2 ,
==================================
proxy对象的方法有:
add ,
equals ,
toString ,
hashCode ,
isProxyClass ,
getInvocationHandler ,
getProxyClass ,
newProxyInstance ,
wait ,
wait ,
wait ,
getClass ,
notify ,
notifyAll ,
===================================
proxy的父类: class java.lang.reflect.Proxy
====================================
proxy实现的接口有:
dynamic.proxy.UserService ,
====================================
运行结果:
======执行add方法之前============
--------------------add---------------
======执行add方法之后============
true
true
==================================
proxy的类型是: class com.sun.proxy.$Proxy0
===================================
proxy对象的属性有:
m1 ,
m3 ,
m0 ,
m2 ,
==================================
proxy对象的方法有:
add ,
equals ,
toString ,
hashCode ,
isProxyClass ,
getInvocationHandler ,
getProxyClass ,
newProxyInstance ,
wait ,
wait ,
wait ,
getClass ,
notify ,
notifyAll ,
===================================
proxy的父类: class java.lang.reflect.Proxy
====================================
proxy实现的接口有:
dynamic.proxy.UserService ,
====================================
运行结果:
======执行add方法之前============
--------------------add---------------
======执行add方法之后============
从上面的输出结果我们可以得出下面的结论:
1、proxy这个对象所对应的那个类的定义如下:
public class $Proxy0 extends Proxy implements Uservice{
//...............
}
2、$Proxy0这个类并没有保存在我们的磁盘中。这个类是java虚拟机在执行代码
期间根据需求动态创建出来的。java虚拟机创建$Proxy0这个类是直接生成字
节码文件并且执行$Proxy0的对象proxy的相关方法来“隐式”执行了“增强操作”。
1、proxy这个对象所对应的那个类的定义如下:
public class $Proxy0 extends Proxy implements Uservice{
//...............
}
2、$Proxy0这个类并没有保存在我们的磁盘中。这个类是java虚拟机在执行代码
期间根据需求动态创建出来的。java虚拟机创建$Proxy0这个类是直接生成字
节码文件并且执行$Proxy0的对象proxy的相关方法来“隐式”执行了“增强操作”。
分析到这里,可能还是会对动态代理的“隐式”执行操作是怎样进行的理解的不够清楚。
接下来的第二篇来通过分析Proxy这个类和$Proxy0这个类的大概的源码来进一步讲解。
接下来的第二篇来通过分析Proxy这个类和$Proxy0这个类的大概的源码来进一步讲解。
从更底层来理解jdk动态代理技术的实现。
0 0
- java语言代理模式
- 代理模式(java语言实现)
- 代理模式(Proxy)------基于JAVA语言
- 大白话讲解设计模式之:代理模式 Java语言实现
- 从java语言看 代理模式和反射原理
- Java代理之代理模式
- java代理模式---静态代理
- java代理模式--动态代理
- 代理模式&java动态代理
- JAVA代理模式--静态代理
- JAVA代理模式--动态代理
- JAVA动态代理 代理模式
- Java代理模式-静态代理
- java代理模式-动态代理
- Java代理模式 静态代理 动态代理
- JAVA代理模式与动态代理模式
- JAVA代理模式与动态代理模式
- JAVA代理模式与动态代理模式
- Where is the way to 5G wireless?
- Struts2—Action
- uva 401 Palindromes
- JavaScript闭包及实现循环绑定事件
- HDU 2051 Bitset
- java语言代理模式
- LEETCODE: Divide Two Integers
- 如何查看当前Ubuntu的版本
- HDU 2057 A + B Again
- Error:Failed to find: com.android.support:support-v4:20.+ 之类的错误解决方案
- 日志-14-12-14
- linux下syslog使用说明
- 倍战捶豆言唇汉匾嗽稳痪嚷贝杏痪
- 粗悍侔卦昭子弛忱淹虐僬敖芍呵廖