JAVA动态代理

来源:互联网 发布:哪家淘宝可以套现 编辑:程序博客网 时间:2024/06/05 16:13


代理模式

  • 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。

  • 在某些情况下,一个客户不想或不能直引用另一对象,而代对可在客户端和目标对象之间起到中介的作用。

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

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

  • 代理角色:内部含有对真实对象的引用;提供和真实对象一致的接口以便在任何时候都能代替真实对象;可以在执行真实对象的操作时,附加操作。

  • 真实角色:真实对象,被代理。

//客户端public class Client{    public static void main(String[] args)    {        Subject subject = new ProxySubject();                subject.request();    }}//抽象角色,代理角色和真实角色都实现或继承他public abstract class Subject{    public abstract void request();}//代理角色public class ProxySubject extends Subject{    private RealSubject realSubject; //真实角色的引用        public void request()    {        this.preRequest(); //                if(null == realSubject)        {            realSubject = new RealSubject();        }                realSubject.request(); //                this.postRequest(); //    }        private void preRequest()    {        System.out.println("pre request");    }        private void postRequest()    {        System.out.println("post request");    }}//真实角色public class RealSubject extends Subject{    public void request()    {        System.out.println("From real subject.");    }}

动态代理

就静态代理而言:真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决

动态代理类

• Java动态代理类位于java.lang.reflect包下,一般主要
涉及到以下两个类:
• (1)Interface InvocationHandler:该接口中仅定义了
一个方法
– public 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接口中声明过的方法
)

• 所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何来用。当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作

• 通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系

动态代理步骤

1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法

2.创建被代理的类以及接口

3.通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class[] interfaces, InvocationHandlerh) 创建一个代理

4.通过代理调用方法

public class Client{    public static void main(String[] args)    {        RealSubject realSubject = new RealSubject();        InvocationHandler handler = new DynamicSubject(realSubject);        Class<?> classType = handler.getClass();        // ÏÂÃæµÄŽúÂëÒ»ŽÎÐÔÉú³ÉŽúÀí        Subject subject = (Subject) Proxy.newProxyInstance(classType                .getClassLoader(), realSubject.getClass().getInterfaces(),                handler);        subject.request();        System.out.println(subject.getClass());    }}public class DynamicSubject implements InvocationHandler{    private Object sub;        public DynamicSubject(Object obj)    {        this.sub = obj;    }        //正是由于这里采用了反射,所以才避免了静态代理和真实对象绑定的//问题。    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable    {        System.out.println("before calling: " + method);                method.invoke(sub, args);                System.out.println(args == null);                System.out.println("after calling: " + method);                return null;    }    }public class RealSubject implements Subject{    public void request()    {        System.out.println("From real subject!");    }}//一致性接口,真实对象和动态生成的代理对象都要实现。public interface Subject{    public void request();}

另一个例子

public class Client<T> implements InvocationHandler{    T obj;    public Client(T obj){        this.obj = obj;    }        @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        // TODO Auto-generated method stub        System.out.println("Proxy!");                return method.invoke(obj,args);    }        public static void main(String[] args) {        List<Integer> list = new LinkedList<>();        Client<List<Integer>> handler = new Client<>(list);                //pro为动态生成的代理对象        @SuppressWarnings("unchecked")        List<Integer> pro = (List<Integer>)Proxy.newProxyInstance(Handler.class.getClassLoader(),                 list.getClass().getInterfaces(),handler);                //通过代理pro调用add方法。pro会让handler通过调用invoke调用add方法        for(int i=0;i<10;i++)            pro.add(i);                for(Iterator<Integer> it =pro.iterator();it.hasNext();System.out.print(it.next()));            }   }

0 0