代理模式:为其他对象提供一种代理以控制对这个对象的访问。
最简单的代理模式,分为三种角色:
抽象主题角色:代理类与被代理共同实现的接口,内部定义了最普通的业务类型。
具体主题角色:被代理类,具体实现接口的方法。
代理主题角色:代理类,继承主题接口,并生成与被代理类方法名一致的方法,并且调用被代理类的方法。
//抽象主题角色 public interface ISubject{ //具体业务方法 public void method(); } //具体主题角色 public class Subject implements ISubject{ public void method(){ //业务方法 } } //代理主题角色 public class SubjectProxy implements ISubject{ private ISubject subject = null; public SubjectProxy(ISubject subject){ this.subject = subject; } public void method(){ this.before(); subject.method; this.after(); } private void before(){ //前置增强业务逻辑 } private void after(){ //后置增强逻辑 } } //调用 public static void main(String args[]){ ISubject subject = new Subject(); ISubject proxy = new SubjectProxy(subject); proxy.method(); }
代理模式的扩展
1、普通代理
调用者只能调用代理对象,并且只知道代理对象类型,不知被代理对象类型。
//普通代理 //抽象主题角色 public interface ISubject{ //具体业务方法 public void method(); } //具体主题角色 public class Subject implements ISubject{ public Subject(ISubject subject) throws Exception{ if(subject == null){ throw new Exception(""); }else{ } } public void method(){ //业务方法 } } //代理主题角色 public class SubjectProxy implements ISubject{ private ISubject subject = null; public SubjectProxy(){ try{ subject = new Subject(this); }catch(Exception e){ } } public void method(){ this.before(); subject.method; this.after(); } private void before(){ //前置增强业务逻辑 } private void after(){ //后置增强逻辑 } } //调用 public static void main(String args[]){ ISubject proxy = new SubjectProxy(); proxy.method(); }
2、强制代理
必须通过实例化被代理对象,然后通过被代理对象的指定的代理对象进行方法调用。
// 强制代理 // 抽象主题角色 public interface ISubject { // 具体业务方法 public void method(); // 找到代理类 public ISubject getProxy(); } // 具体主题角色 public class Subject implements ISubject { private ISubject proxy = null; public ISubject getProxy() { this.proxy = new Subject(this); return this.proxy; } public void method() { if (this.isProxy()) { // 业务方法 } else { } } // 校验是否是代理访问 private boolean isProxy() { if (this.proxy == null) { return false; } else { return true; } } } // 代理主题角色 public class SubjectProxy implements ISubject { private ISubject subject = null; public SubjectProxy(ISubject subject) { this.subject = subject; } public void method(){ this.before(); subject.method(); this.after(); } private void before() { // 前置增强业务逻辑 } private void after() { // 后置增强逻辑 } public ISubject getProxy(){ return this; } } // 调用 public static void main(String args[]) { ISubject subject = new Subject(); ISubject proxy = subject.getProxy(); proxy.method(); }
代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上作增强,这种增强的本质通常就是对目标对象的方法进行拦截和过滤。
动态代理
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。使用JDK提供的动态代理接口InvocationHandler对被代理类的方法进行代理。
//抽象主题public interface Subject{ //业务操作方法 public void doSomething(String str);}
//真实主题public class RealSubject implements Subject{ //业务操作 public void doSomething(String str){ System.out.println("do something --> " + str); }}
真实主题实现主题类接口
//动态代理的Handler类public class MyInvocationHandle implements InvocationHandle { // 被代理对象 private Object target = null; // 通过构造函数传递一个对象 public MyInvocationHandle(Object target) { this.target = target; } // 代理方法 可在此方法中对原方法进行增强 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 执行被代理方法 return method.invoke(this.target, args); }}
所有的动态代理实现方法都通过invoke的方法调用。
//动态代理类public class DynamicProxy{ public static T newProxyInstance(ClassLoader loader,Class [] interfaces,InvocationHandler h){ //寻找JoinPoint连接点,AOP框架使用元数据定义 if(true){ //通知类的方法调用 (new BeforeAdvice()).exec(); } return (T)Proxy.newProxyInstance(loader, interfaces, h); }}//具体业务的动态代理类public class SubjectDynamicProxy extends DynamicProxy{ public static T newProxyInstance(Subject subject){ //获取ClassLoader ClassLoader loader = subject.getClass().getClassLoader(); //获取接口数组 Class [] classes = subject.getClass().getInterfaces(); //获取hander InvocationHandler handler = new MyInvocationHandler(subject); return newProxyInstance(loader,classes,handler); }}
调用 newProxyInstance(c.getClassLoader(),c.getInterfaces,InvocationHandler h)方法, 重新生成了一个对象,c.getInterfaces找到了类的所有接口,然后实现了接口的所有方法,但是方法都是空的,这些方法都由InvocationHandle方法来接管。
//具体调用public class Client{ public static void main(String[] args){ Subject subject = new RealSubject(); Subject proxy = SubjectDynamicProxy.newProxyInstance(subject); proxy.doSomething(""); }}