黑马程序员 动态代理
来源:互联网 发布:如何供货给淘宝 编辑:程序博客网 时间:2024/06/05 15:24
动态代理技术其实并不复杂,它是一个面向方面的程序设计,简单点说,就是不是针对一种特定的方法而设计。比如很多系统中都要记录安全信息、事物信息、生成日志,我们不可能一个方法一个方法的往上加代码吧,那样累赘而麻烦。这就需要用到一个类代理需要的类,然后再代理类中使用我们需要的方法,只要加上了代理类,再调用其中的所有方法都是调用我们代理类上自己定义的方法,这样就实现了面向方面程序设计。
AOP(Object Oriented Programming):
在实际的网络中,我们也很少直接使用需要客服端的信息,中间都需要加载一个代理,这样方便与操作。
代理类的建立:
既然是代理一个类,那么我们肯定无法确定需要代理的是什么类,而又要用到那个类中的方法,这肯定是使用了反射。
代理类的建立,必须得到与需要使用类有关联的代理类的Class文件对象。
通过Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces);
它必须要接收一个类加载器,和要实现代理接口的Class对象。
既然要使用Proxy这个类,就必须查看其中的构造方法、函数方法。
既然能得到Proxy的Class对象,不妨用反射列出其中的方法,可用如下方法做:
System.out.println("-------------------Proxy Method-----------------------------");//通过反射返回类中方法数组Method[] methods = clazzProxy.getMethods();for(Method method: methods){String name = method.getName();StringBuilder sb = new StringBuilder(name);sb.append("(");//得到每个方法的参数,通过 getParameterTypes() 方法Class[] clazzParams = method.getParameterTypes();//将参数加入一个StringBuilder,并按照格式打印for(Class clazzParam: clazzParams){sb.append(clazzParam.getName()).append(",");}if(clazzParams.length!=0)sb.deleteCharAt(sb.lastIndexOf(","));sb.append(")");System.out.println(sb.toString());}同理得到构造方法,打印结构发现Proxy只有一个构造方法
com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler)其中的方法有:
-------------------Proxy Method-----------------------------hashCode()equals(java.lang.Object)toString()add(java.lang.Object)contains(java.lang.Object)isEmpty()size()toArray()toArray([Ljava.lang.Object;)addAll(java.util.Collection)iterator()remove(java.lang.Object)clear()containsAll(java.util.Collection)removeAll(java.util.Collection)retainAll(java.util.Collection)isProxyClass(java.lang.Class)getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)getInvocationHandler(java.lang.Object)getClass()notify()notifyAll()wait(long)wait(long,int)wait()大多都是Object类中方法,其中的newProxyInstance建立实例的方法也与InvocationHandler有关,可以推测动态代理主要是通过此方法来实现的。
查看API文档可知,newProxyInstance()返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。就是说创建出了这个代理,就能完全实现原有接口中的所有功能。那么既然这个是个代理类,当然也可以自己添加新的功能进去,这便是动态代理了,只要我们需要,完全可以加载自己想要方法进去。
下面是一个用动态代理植入广告的程序,我们也可以随意更换其中的广告内容:
这是一个sayHello的接口:
package cn.itcast.day3;public interface SayHello {void sayHello();}此类实现了sayHello接口,也是我们需要代理的类,在其收尾植入广告:
package cn.itcast.day3;public class TestSayHello implements SayHello {public void sayHello() {System.out.println("Hello sky!");}}创建一个代理对象,并加入植入语句:
package cn.itcast.day3;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyTest {public static void main(String[] args) throws Exception{Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);//将接口定义成目标类final TestSayHello target = new TestSayHello();// 抽取出获取代理的方法,并调用之SayHello proxy2 = (SayHello)getProxy(target, new Test()); proxy2.sayHello();}private static Object getProxy(final Object target, final Test test) {//newProxyInstance接收3个参数 ClassLoader, Interfaces, InvocationHandlerObject proxy2 = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), //实现InvocationHandler中的inovke方法 new InvocationHandler() {//invoke接收的3个参数实际上就是需要代理类中对象、方法、参数public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {test.beforeMethod();//调用方法前加入的植入Object obj = method.invoke(target,args);test.behindMethod(method); //调用方法前加入的植入return obj;}});return proxy2;}}最后写需要植入的内容:
package cn.itcast.day3;import java.lang.reflect.Method;public class Test {long startTime = 0;public void beforeMethod(){System.out.println("我是插入的广告");startTime = System.currentTimeMillis();}//返回调用此方法使用的时间public void behindMethod(Method method){long endTime = System.currentTimeMillis();System.out.println(method.getName()+":runtime--"+(endTime-startTime));}}打印结果:
我是插入的广告Hello sky!sayHello:runtime--0成功植入广告,并打印出时间,知道这个动态代理的原理后,以后再使用相同的方法时候就简单的多,并且之后的框架如ssh都是基于动态代理产生的,有助于我们理解框架的构建。
- 黑马程序员 动态代理
- 黑马程序员-动态代理
- 黑马程序员 动态代理
- 黑马程序员-动态代理
- 黑马程序员--动态代理
- 黑马程序员--动态代理
- 黑马程序员-动态代理
- 黑马程序员---------动态代理
- 黑马程序员-动态代理
- 黑马程序员-动态代理
- 黑马程序员-动态代理
- 黑马程序员 动态代理
- 黑马程序员-动态代理
- 黑马程序员------动态代理
- 黑马程序员 动态代理
- 黑马程序员----动态代理
- 黑马程序员-----动态代理
- 黑马程序员----动态代理
- EF直接更新数据(不需查询)
- 《黑马程序员》 鼠标和键盘监听器 窗体事件 图形化管理界面 day22
- Debian ibus配置
- 我的WCF4 Rest Service及Entity Framework with POCO之旅(一)——创建一个基本的RESTful Service
- Debian安装的Chromium-browser中文显示不正常解决方法
- 黑马程序员 动态代理
- LeetCode | Median of Two Sorted Arrays
- CommonLisp环境搭建及HelloWorld
- IT零起步-CentOS6.4部署PPTPVPN服务器
- 【Gordon's Great Escape】美食大冒险第二季第一集双语字幕
- 黑马程序员 银行业务调度系统
- 黑马程序员 交通灯管理系统
- OJ中java,C++输入输出重定向的方法
- asp.net发送邮件