spring AoP学习 -----spring设计模式之代理模式
代理模式:对其他对象提供一种代理以控制对这个对象的访问。代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。
代理模式中一般涉及4中角色:
InterfaceSubject :该接口是对被访问者或者被访问资源的抽象。
SubjectImpl:被访问者或者被访问资源的具体实现类,实现了InterfaceSubject
SubjectProxy:被访问者或者被访问资源的代理实现类,该类持有一个InterfaceSubject接口的实例
Client:代表访问者的抽象角色,Client将会访问InterfaceSubject类型的对象或者资源,在这个情景中,Client无法直接访问到InterfaceSubject资源,而是通过代理类SubjectProxy去实现。下面是一个简单的示例:
public interface ProxyISubject { String request(); }
public class ProxySubjectImpl implements ProxyISubject{ @Override public String request() { return "OK"; // TODO Auto-generated method stub } }
public class ProxySubjectProxy implements ProxyISubject{ private static final Log logger = LogFactory.getLog(ProxySubjectProxy.class); private ProxyISubject proxyISubject; @Override public String request() { // TODO Auto-generated method stub TimeOfDay startTime = new TimeOfDay(0,0,0); TimeOfDay endTime = new TimeOfDay(5,59,59); TimeOfDay currentTime = new TimeOfDay(); if(currentTime.isAfter(startTime)&¤tTime.isBefore(endTime)) return null; String result = proxyISubject.request(); return "Proxy:" + result; } public void LogSubjectProxy(ProxyISubject iSubject){ this.proxyISubject = iSubject; } public ProxyISubject getProxyISubject() { return proxyISubject; } public void setProxyISubject(ProxyISubject proxyISubject) { this.proxyISubject = proxyISubject; } }
public class ProxyClient{ @Test public void TestProxy(){ ProxySubjectProxy proxy = new ProxySubjectProxy(); proxy.setProxyISubject(new ProxySubjectImpl()); //proxy.setProxyISubject((ProxyISubject)Proxy.newProxyInstance(ProxySubjectProxy.class.getClassLoader(), new Class[] {ProxyISubject.class}, new DynamicProxyRequestCtrlInvocationHandler(new ProxySubjectImpl()))); assertEquals("Proxy:OK", proxy.request()); } }
静态代理模式的缺点:对于相同的横切逻辑,如果要插入到不同的目标当中的时候,需要重新去实现Proxy代理类。
动态代理:在JDK1.3之后引入了一种称之为动态代理的机制,使用该机制,我们可以指定的接口在系统运行期间动态地生成代理对象,动态代理机制的实现主要有一个类和一个接口组成,即reflect.Proxy 和 reflect.InvocationHandler.
其中InvocationHandler就是我们实现横切逻辑的地方,作用跟Advice一样。缺陷:动态代理机制只能对实现了相应接口的类使用,因此在默认的情况下,如果对象实现了某个接口,这采用动态代理机制为某个生成代理对象实现,如果没有,这使用一种CGLIB的动态字节码生成类库,为目标生成动态代理实例。
InvocationHandler示例:
public class DynamicProxyRequestCtrlInvocationHandler implements InvocationHandler{ private static final Log logger = LogFactory.getLog(DynamicProxyRequestCtrlInvocationHandler.class); private Object target; public DynamicProxyRequestCtrlInvocationHandler(Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub if(method.getName().equals("request")){ TimeOfDay startTime = new TimeOfDay(0,0,0); TimeOfDay endTime = new TimeOfDay(5,59,59); TimeOfDay currentTime = new TimeOfDay(); if(currentTime.isAfter(startTime)&¤tTime.isBefore(endTime)){ logger.debug("the time is error"); return null; } logger.info("the time is right"); return method.invoke(target, args); } return null; } }