最近在看Spring,其AOP的实现 涉及到代理模式:分为静态模式和动态模式,特此记之。代码全部用Spring实现:
一、GOF 的代理模式(Proxy Pattern),静态代理
一个客户(Client)不想或者不能够直接引用一个对象(RealSubject),而代理对象(Proxy)给此对象提供一个代理,并由代理对象控制对原对象的引用(realSubject.Request()),在客户端和目标对象之间起到中介的作用;
应用:
Spring的AOP
如用户Client希望加入切面,如“日志”功能,又不希望修改原程序,那么为每一个对象建立一个通用的Proxy,将切面功能加入Proxy
.Net 的 XML Web Services,Client端都是通过本地Proxy class来转发对Remote Objects or Services的请求,和获取来自Remote的响应
例程:
IHello.java (subject)
public interface IHello {
public void hello();
}
Hello.java (RealSubject)
public class Hello implements IHello {
public void hello() {
System.out.println("say hello");
}
HelloProxy.java (Proxy)
public class HelloProxy implements IHello{
private IHello helloOject;
public HelloProxy(IHello helloOject) {
this.helloOject = helloOject;
}
public void hello() {
System.out.println("began before method");
this.helloOject.hello();
System.out.println("began after method");
}
}
MyMain.java (client)
public class MyMain {
public static void main(String[] args) {
BeanFactory factory=new FileSystemXmlApplicationContext("mybean.xml");
IHello hello=(IHello)factory.getBean("helloProxy");
hello.hello();
HelloProxy.java (Proxy)
public class HelloProxy implements IHello{
private IHello helloOject;
public HelloProxy(IHello helloOject) {
this.helloOject = helloOject;
}
public void hello() {
System.out.println("began before method");
this.helloOject.hello();
System.out.println("began after method");
}
}
MyMain.java (client)
public class MyMain {
public static void main(String[] args) {
BeanFactory factory=new FileSystemXmlApplicationContext("mybean.xml");
IHello hello=(IHello)factory.getBean("helloProxy");
hello.hello();
}
}
}
二、Java动态代理与静态代理的不足
例程:
MyHandler.java (RealHandler)
public class MyHandler implements InvocationHandler {
private Object delegate;
public void setDelegate(Object delegate) {
this.delegate = delegate;
}
public Object bind(){
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("began before method");
Object result=method.invoke(delegate, args);//注意第一个参数是被代理对象delegate!
System.out.println("began after method");
return result;
}
例程:
MyHandler.java (RealHandler)
public class MyHandler implements InvocationHandler {
private Object delegate;
public void setDelegate(Object delegate) {
this.delegate = delegate;
}
public Object bind(){
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("began before method");
Object result=method.invoke(delegate, args);//注意第一个参数是被代理对象delegate!
System.out.println("began after method");
return result;
}
}
MyMain.java (client)
public static void main(String[] args) {
BeanFactory factory=new FileSystemXmlApplicationContext("mybean.xml");
MyHandler handler=(MyHandler)factory.getBean("helloDProxy");
IHello hello=(IHello)handler.bind();
hello.hello();
}
MyMain.java (client)
public static void main(String[] args) {
BeanFactory factory=new FileSystemXmlApplicationContext("mybean.xml");
MyHandler handler=(MyHandler)factory.getBean("helloDProxy");
IHello hello=(IHello)handler.bind();
hello.hello();
}
问题:静态代理的问题是Proxy不通用和被代理对象耦合太紧,一个代理只能代表一个对象。动态代理则可以代表任何对象