Java 动态代理
2015-10-15 16:37
381 查看
首先,什么是代理?
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
举例:春季回家买票让人代买
Java中的代理模式:
定义
代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。
代理模式不会改变原来的接口和行为,只是转由代理干某件事,代理可以控制原来的目标,例如:代理商,代理商只会买东西,但并不会改变行为,不会制造东西。让我们通过下面的代码好好理解一下这句话。
分类
静态代理和动态代理
先看静态代理利例子:
缺点:
同样,它的优点也成了它致命的缺点。
1、静态代理很麻烦,需要大量的代理类
当我们有多个目标对象需要代理时,我就需要建立多个代理类,改变原有的代码,改的多了就很有可能出问题,必须要重新测试。
2、重复的代码会出现在各个角落里,违背了一个原则:重复不是好味道
我们应该杜绝一次次的重复。
3、在编译期加入,系统的灵活性差
动态代理:在程序运行过程中产生的这个对象
而程序运行过程中产生对象其实就是反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib
Proxy类中的方法创建动态代理类对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
InvocationHandler
Object invoke(Object proxy,Method method,Object[] args)
所谓 Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
再看动态代理的例子:
UserDao.java,UserDaoImpl.java跟上面的相同.
优点:大大地减少了代码的冗余,比如,再来个studentDao,对学生进行管理,也是需要权限验证的,那么,你直接再建一个Proxy 对象代理即可,因为在InvocationHandler 里是通过你要实现的接口的Class对象实现逻辑的,不是硬编码。
看到这里,大概知道了动态代理是干什么的了。可是还依然对Java JDK里的
Proxy类和InvocationHandler接口仍然不够了解,都学到这里了,知其然当然要知其所以然啦。
于是,上网看大神更上一层楼
/article/1542173.html点击打开链接
------------------------二次学习Proxy类和InvocationHandler接口更深理解的分界线------------------------------
JDK的自带的动态代理动态生成了字节码(当然当中还用了反射),只是他的生成字节码的方式
必须和接口绑定,而cglib,并不是正对接口来而是针对普通类来动态的生成字节码
动态代理动态体现在运行时生成代理类字节码,然后由InvocationHandler要代理的接口(从$Proxy0的源码可以看出,动态代理类不仅代理了显示定义的接口中的方法,而且还代理了java的根类Object中的继承而来的equals()、hashcode()、toString()这三个方法,并且仅此三个方法。
总结一下动态代理实现过程:
1. 通过getProxyClass0()生成代理类。
2. 通过Proxy.newProxyInstance()生成代理类的实例对象,创建对象时传入InvocationHandler类型的实例。
3. 调用新实例的方法,即此例中的add(),即原InvocationHandler类中的invoke()方法。
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
举例:春季回家买票让人代买
Java中的代理模式:
定义
代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。
代理模式不会改变原来的接口和行为,只是转由代理干某件事,代理可以控制原来的目标,例如:代理商,代理商只会买东西,但并不会改变行为,不会制造东西。让我们通过下面的代码好好理解一下这句话。
分类
静态代理和动态代理
先看静态代理利例子:
package com.proxy; /* * 用户操作接口 */ public interface UserDao { public abstract void add(); public abstract void delete(); public abstract void update(); public abstract void find(); }
package com.proxy; public class UserDapImpl implements UserDao{ @Override public void add() { System.out.println("添加功能"); } @Override public void delete() { System.out.println("删除功能"); } @Override public void update() { System.out.println("更新功能"); } @Override public void find() { System.out.println("查找功能"); } }
package com.proxy; public class UserDaoImplProxy implements UserDao{ @Override public void add() { System.out.println("权限校验"); System.out.println("添加功能"); System.out.println("日志记录"); } @Override public void delete() { System.out.println("权限校验"); System.out.println("删除功能"); System.out.println("日志记录"); } @Override public void update() { System.out.println("权限校验"); System.out.println("修改功能"); System.out.println("日志记录"); } @Override public void find() { System.out.println("权限校验"); System.out.println("查找功能"); System.out.println("日志记录"); } }
package com.proxy; public class UserDaoDemo { public static void main(String[] args) { //用户管理 的基本操作 UserDao ud=new UserDapImpl(); ud.add(); ud.delete(); ud.update(); ud.find(); System.out.println("--------------"); //实际上,对用户的操作,并不是所有的人都可以,我们来个权限验证 //而这个权限验证我们并不自己做,而是交给别人做 UserDao ud2=new UserDaoImplProxy(); ud2.add(); ud2.delete(); ud2.update(); ud2.find(); System.out.println("--------------"); } }
缺点:
同样,它的优点也成了它致命的缺点。
1、静态代理很麻烦,需要大量的代理类
当我们有多个目标对象需要代理时,我就需要建立多个代理类,改变原有的代码,改的多了就很有可能出问题,必须要重新测试。
2、重复的代码会出现在各个角落里,违背了一个原则:重复不是好味道
我们应该杜绝一次次的重复。
3、在编译期加入,系统的灵活性差
动态代理:在程序运行过程中产生的这个对象
而程序运行过程中产生对象其实就是反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib
Proxy类中的方法创建动态代理类对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
InvocationHandler
Object invoke(Object proxy,Method method,Object[] args)
所谓 Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
再看动态代理的例子:
UserDao.java,UserDaoImpl.java跟上面的相同.
package com.dynaproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 采用JDK动态代理必须实现InvocationHandler接口,采用Proxy类创建相应的代理类 * */ public class MyInvocationHandler implements InvocationHandler{ private Object target;//目标对象,代理对象 public MyInvocationHandler(Object target){ this.target=target; } /** * 反射,这样你可以在不知道具体的类的情况下,根据配置的参数去调用一个类的方法。在灵活编程的时候非常有用。 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验");//代理所做的事情 Object result=method.invoke(target, args); System.out.println("日志记录");//代理所做的事情 return result; // 返回的是代理对象 } }
package com.dynaproxy; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { UserDao ud=new UserDapImpl(); //准备对ud做一个代理对象 MyInvocationHandler handler=new MyInvocationHandler(ud); //生成ud的代理对象 UserDao proxy=(UserDao)Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), handler); //用代理对象做 权限工作 及完成ud的操作 proxy.add(); proxy.delete(); proxy.update(); proxy.find(); } }
优点:大大地减少了代码的冗余,比如,再来个studentDao,对学生进行管理,也是需要权限验证的,那么,你直接再建一个Proxy 对象代理即可,因为在InvocationHandler 里是通过你要实现的接口的Class对象实现逻辑的,不是硬编码。
看到这里,大概知道了动态代理是干什么的了。可是还依然对Java JDK里的
Proxy类和InvocationHandler接口仍然不够了解,都学到这里了,知其然当然要知其所以然啦。
于是,上网看大神更上一层楼
/article/1542173.html点击打开链接
------------------------二次学习Proxy类和InvocationHandler接口更深理解的分界线------------------------------
JDK的自带的动态代理动态生成了字节码(当然当中还用了反射),只是他的生成字节码的方式
必须和接口绑定,而cglib,并不是正对接口来而是针对普通类来动态的生成字节码
public static Object newProxyInstance(ClassLoader loader,Class<?>[interfaces,InvocationHandler h) 分解步骤:以创建某一接口 Foo 的代理为例子: InvocationHandler handler = new MyInvocationHandler(...); //生成代理类的Class对象(字节码) Class proxyClass = Proxy.getProxyClass( Foo.class.getClassLoader(), new Class[] { Foo.class }); //通过反射,根据Class对象获取构造方法,再 newInstance,传入hanlder(proxy构造函数 指定参数) Foo f = (Foo) proxyClass. getConstructor(new Class[] { InvocationHandler.class }). newInstance(new Object[] { handler });通过网上大神对newProxyInstance的源码深度解析点击打开链接,以及以上newProxyInstance的生成原理,
动态代理动态体现在运行时生成代理类字节码,然后由InvocationHandler要代理的接口(从$Proxy0的源码可以看出,动态代理类不仅代理了显示定义的接口中的方法,而且还代理了java的根类Object中的继承而来的equals()、hashcode()、toString()这三个方法,并且仅此三个方法。
总结一下动态代理实现过程:
1. 通过getProxyClass0()生成代理类。
2. 通过Proxy.newProxyInstance()生成代理类的实例对象,创建对象时传入InvocationHandler类型的实例。
3. 调用新实例的方法,即此例中的add(),即原InvocationHandler类中的invoke()方法。
相关文章推荐
- javax.naming.NamingException: Cannot create resource instance
- java开源验证框架OVAL帮助文档
- Spring Boot实践之Hello World
- JavaWeb中文乱码问题
- java--通过JDBC方式读取xml文件简单实例
- eclipse maven启动报错
- Java中堆与栈的关系
- Spring MVC @ResponseBody返回中文字符串乱码问题
- springmvc参数的传递
- springmvc参数的传递
- java定时器的几种用法
- 文件内容搜索器
- Java 可变长参数列表
- Java读写文件方法总结
- Java开发中的23种设计模式详解一
- [实例]JAVA生成字母+随机数字并生成文件
- java命令查看字节码文件
- Java MVC + ORM框架 Nano Framework简介
- 二叉树(java实现)
- JAVA中的接口和抽象类(转)