黑马程序员(七)1.5新特性动态代理

来源:互联网 发布:js统计下载次数 编辑:程序博客网 时间:2024/06/18 14:28

Java动态代理一——动态类Proxy的使用

1.什么是动态代理?

答:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。
2.为什么使用动态代理?

答:因为动态代理可以对请求进行任何处理

3.使用它有哪些好处?

答:因为动态代理可以对请求进行任何处理
4.哪些地方需要动态代理?

答:不允许直接访问某些类;对访问要做特殊处理等

1.      代理模式

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式一般涉及到的角色有:

抽象角色:声明真实对象和代理对象的共同接口;

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献1)

以下以《Java与模式》中的示例为例:

package day3;     //总结几点。。。要代理的类必须继承了类或者实现了接口。//抽象角色:abstract public class Subject{    abstract public void request();}//真实角色:实现了Subject的request()方法。 class RealSubject extends Subject{       public RealSubject()       {       }             public void request()       {              System.out.println("From real subject.");       }}//代理角色:class ProxySubject extends Subject{    private RealSubject realSubject;  //以真实角色作为代理角色的属性             public ProxySubject()       {       }        public void request(){  //该方法封装了真实对象的request方法{        preRequest();               if( realSubject == null ){                     realSubject = new RealSubject();              }        realSubject.request();  //此处执行真实对象的request方法        postRequest();       }     private void preRequest()    {        System.out.println("开始");    }     private void postRequest()    {       System.out.println("结束");    }}
//客户端调用Subject subj=new ProxySubject();subj.request();

2.动态代理类

       Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。


(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:

Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。

Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

//小试牛刀玩活。顺便回忆了下反射。。下面开始正题。//这种方式是获得动态代理class对象然后反射构造方法。通过反射的构造方法创建Collection的动态代理对象。Class collection=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);Constructor constructor=collection.getConstructor(InvocationHandler.class);Collection proxy1=(Collection) constructor.newInstance(new MyInvocationHandler());//麻烦的创建动态代理类对象方式。

final ArrayList target=new ArrayList();MyAdvice advice=new MyAdvice();Collection proxy2 = (Collection)gerProxy(target,advice);proxy2.add("abc");proxy2.add("ffbc");System.out.println(proxy2.size());}//把动态代理对象创建成一个框架模式,方便使用,以后无论任何一个对象都可以调用。private static Object gerProxy(final Object target,final MyAdvice advice) {Object proxy=Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces()/*目标的所有实现接口*/,new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubadvice.proAdvice(method);//开始代码。可以直接在外部advice里调试Object value= method.invoke(target, args);//调用实际对象的方法。这也是联系最紧密的一步advice.PostAdvice(method);//同上。结束代码直接在外部调试即可return value;}});return proxy;}
下面是自己创建的调试开始头和结束头的代码。。自己随意添加
package day3;import java.lang.reflect.Method;public class MyAdvice {MyAdvice(){}public void proAdvice(Method method){System.out.println(method.getName()+"开始");}public void PostAdvice(Method method){System.out.println(method.getName()+"结束");System.out.println(method.getName()+":running time of:::::::");}}



0 0
原创粉丝点击