静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
静态代理在感觉上和装饰设计模式很像
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();
}
}