java中的静态代理和动态代理,入门整理
静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
静态代理在感觉上和装饰设计模式很像
1)、在代理类中实现被代理类实现的所有接口,这样保证了被代理类所能实现的方法,代理类也能实现,保证了两边行为的一致性,代理类就能转型为被代理类,当作被代理类处理。而代理中有被代理类的对象,这样,在代理类的内部实现接口方法时就能调用被代理类的方法,从而进行对被代理类的封装。
简单的示范:
package cn.edu.cjl; public interface Subject { public void replace(); }
package cn.edu.cjl; public class RealSubject implements Subject{ @Override public void replace() { // TODO Auto-generated method stub System.out.println("real subject..."); } }
package cn.edu.cjl; public class daili implements Subject { RealSubject subject; @Override public void replace() { System.out.println("before..."); if(subject==null){ subject=new RealSubject(); } subject.replace(); System.out.println("after..."); } }
package cn.edu.cjl; public class Client { public static void main(String[] args) { Subject subject=new daili(); subject.replace(); } }
代码中定义接口Subject,真实的实现类是RealSubject,但是在在主方法中调用的是daili类,在daili类中同样实现了Subject接口,但是真实上调用的是RealSubject类的方法。这就是静态代理。
静态代理可以解决直接访问类方法带来的问题,但是本身也有问题,就是当大量的使用静态代理时类的个数将双倍的增加,不利于程序的管理。
动态代理使用了反射技术,一个代理类可以为任意类提供代理。
代理类必须实现InvocationHandler接口,
对代理实例调用方法时,将对方法调用进行编码并将其指派到它的代理程序的 invoke
方法。
invoke方法运用反射技术,通过java.lang.reflect.Proxy类中提供的静态方法 newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序,也就是代理类实现的InvocationHandler接口中的invoke方法中,这个方法的各个参数的意思是
ClassLoader loader:类加载器,定义代理类的类加载器,可以任意指定。
Class<?>[] interfaces: 被代理类所实现的所有接口的class数组,可以用class对象的getInterfaces()方法得到。
InvocationHandler h:实现了InvocationHandler接口的对象。
简单的事例:
package cn.edu.cjl.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class proxy implements InvocationHandler { private Object object; public proxy(Object obj){ this.object=obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); Object resultObject= method.invoke(object, args); System.out.println("after"); return resultObject; } }
package cn.edu.cjl.proxy; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { Subject subject = null; RealSubject rSubject = new RealSubject(); proxy proxy = new proxy(rSubject); subject = (Subject) Proxy.newProxyInstance(Client.class .getClassLoader(), rSubject.getClass().getInterfaces(), proxy); subject.replace(); } }