一.代理模式:
代理模式模式的作用:为其他对象提供了一种代理以控制对这个对象的访问。也就是说通过一个中介来控制这个对象的使用。
代理模式涉及到的角色有:
1).抽象角色:声明真实对象和代理对象的接口(也可以使用抽象类)。
2).代理角色:代理对象角色内部含有对真实对象角色的引用。从而可以操作真实对象,同时代理对象提供与真实对象的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时附加其他操作,相当于对真实对象的封装。
3).真实角色:代理角色所代表的真实对象,是我们最终引用的对象。
静态代理模式的实现:
抽象类或接口(我用抽象类实现):
public abstract class Nozzle { //真实角色和代理角色都要实现的方法。 public abstract void role(); }
真实角色:
public class RealRole extends Nozzle{ //真实角色 public void role() { System.out.println("RealRole!"); } }
代理角色:
public class ProxyRole extends Nozzle { //代理角色 //需要持有一个真实对象的引用 private RealRole role ; //这是中介 public void role() { if(null == role){ role = new RealRole(); } firstThing();//可以随意使用。 role.role();//真实角色完成的事情。 secondThing(); } public void firstThing(){ System.out.println("真实操作之前附加的操作!"); } public void secondThing(){ System.out.println("真实操作之后附加的操作!"); } }
测试类:
public class Test { public static void main(String[] args) { Nozzle role = new ProxyRole(); role.role(); } }
打印:
真实操作之前附加的操作! RealRole! 真实操作之后附加的操作!
这是静态代理模式,静态代理模式有着很大的弊端,因为使用这种代理模式,那么真实角色必须是实现存在的,必将其作为代理对象的内部属性,而且一个真实角色对应一个代理角色,那这样会造成大量的资源浪费。所以由此有了动态代理模式。
动态代理模式:
java动态代理类位于java.lang.reflect包下。主要涉及到两个类的使用:
1).Interface InvocationHandler:该接口中仅定义了一个方法
public Object invoke(Object obj,Method method,Object[] args)
在实际的使用中,第一个参数obj一般是值代理类,第二个参数method是指被代理的方法,第三个参数args[]是指该方法的参数数组。这个方法在代理类中动态的实现。
2).Proxy:该类即为动态代理类。就是如同上例中的ProxyRole。
用到的方法:
protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。
static Class getProxyClass(ClassLoader loader,Class[] interface):获得一个代理类,其中loader是类装载器,interface是真实类所拥有的全部接口的数组。
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用。
动态代理类:
接口:
public interface Subject { public void request(); }
真实角色:
public class RealSubject implements Subject{ public void request() { System.out.println("From real subject!"); } }
动态代理角色:
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("brfore calling: "+method); //控制着RealSubject方法中的request()方法的执行。 method.invoke(sub,args); System.out.println("after calling"+method); return null; } }
测试类:
public class Client { public static void main(String[] args) { RealSubject r = new RealSubject(); InvocationHandler handler = new DynamicSubject(r); Class<?> c = handler.getClass(); //动态的生成一个类 ,第一个参数是,第二个参数是该动态类要实现的所有接口所以能正常的转换为Subject类型。第三个是调用所需类回调函数。 Subject sub = (Subject)Proxy.newProxyInstance(c.getClassLoader(),r.getClass().getInterfaces(),handler); //当执行这里的方法时 就会转到上面的handler参数去DynamicSubject中去调用invoke方法。 sub.request(); } }
通过这种方式,被代理的对象(RealSubject)可以在运行时动态的改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject)也可以动态的改变,从而实现了灵活的动态代理模式。
所谓的动态代理类(Dynamic Proxy)是这样的一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该Class的实例当做这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你做实质性的工作,在生成它的实例时你必须提供一个handler,由它来接实际的工作。
动态代理模式的作用:实现了日志和业务的分开,也就是某个类只是要提供了某些业务。
动态代理另一个例子:
public class VectorProxy implements InvocationHandler { private Object proxyObj; public VectorProxy(Object obj){ this.proxyObj = obj; } public static Object factory(Object obj){ Class<?> classType = obj.getClass(); return Proxy.newProxyInstance(classType.getClassLoader(),classType.getInterfaces(),new VectorProxy(obj)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before calling :"+method); if(null != args){ for(Object o :args){ System.out.println(o); } } Object object = method.invoke(proxyObj,args); System.out.println("after calling :"+method); return object; } public static void main(String[] args) { List v = (List)factory(new Vector()); v.add("New"); v.add("York"); } }
打印:
before calling :public abstract boolean java.util.List.add(java.lang.Object) New after calling :public abstract boolean java.util.List.add(java.lang.Object) before calling :public abstract boolean java.util.List.add(java.lang.Object) York after calling :public abstract boolean java.util.List.add(java.lang.Object)