浅谈代理模式(一)"/>
浅谈代理模式(一)
代理模式基础
代理模式基础
- 代理模式是在框架设计中经常使用的一种设计模式。
首先代理模式,可以分为两种,一种是静态代理,一种是动态代理。
- 代理模式属于结构型设计模式。
- 它的作用是为其他对象提供一层代理以控制对类的访问,当我们无法直接访问某一个类时可使用代理模式作为中介。
两种代理从虚拟机加载类的角度来讲,本质上都是一样的,都是在原有类的行为基础上,加入一些多出的行为,甚至完全替换原有的行为。
- 代理类和委托类必须实现同一接口。
动态代理有一个强制性要求,就是被代理的类必须实现了某一个接口,或者本身就是接口,就像我们mybatis中的Mapper。
- 代理模式的优点 :可以在不修改委托类的情况下,为委托类提供新的功能,符合开闭原则。
- 代理模式的应用场景 :
- 为委托类添加统一处理,例如Spring的AOP。
- 提供统一快捷的请求访问,例如mybatis的mapper,spring cloud的feign等等。
静态代理模式
代理模式类图
应用场景和代码实现
现在公司接到一个新项目,老板需要吩咐下面去完成它,一般来说,老板不会亲自去吩咐程序员写代码,而是将项目事宜交给项目经理,由项目经理统一调度,接下来我们实现这个过程。
公司职员接口
public interface Employee {void work();
}
码农
public class Programmer implements Employee {//码农的本职工作就是写代码@Overridepublic void work(){System.out.println("写代码");}
}
项目经理
public class ProjectManager implements Employee {private final Programer programmer;public ProjectManager(){//项目经理选择程序员programmer = new Programmer();}@Overridepublic void work(){System.out.println("项目经理说明项目");this.programmer.work();System.out.println("项目经理验收项目");}
}
这样就完成了一个静态代理模式的过程,总的来说静态代理模式非常简单,就是代理类和委托类实现同样的接口,一切的工作就有代理类来完成,与装饰器模式不同的是,使用者不需要关心委托类的任何操作,只需要跟代理类进行交互就可以了。
一般来说在代理类数量固定,并不太多时,建议使用静态代理,因为动态代理需要在运行时动态生成代理类,会相对较慢。
JDK动态代理
动态代理类图
当我们需要代理一系列类的某些方法时,很显然静态代理就无法满足我们的需求了,我们不能为每一个类型的委托类,创建一个专用的代理类,这时,我们就可以使用动态代理来完成我们的功能。
代码实现
常规日志
public interface IEmployee {String work(String str);
}
public class Programmer implements IEmployee {@Overridepublic String work(String str) {System.out.println(str+"is coding");}
}
public class ProductManager implements InvocationHandler {public IEmployee employee;public ProductManager(IEmployee employee){this.employee = employee;}@Overridepublic Object invoke(Object obj, Method method, Object[] args) {System.out.println("项目经理发布任务");Object result = method.invoke(employee, args);System.out.println("项目经理收集成果");return result;}public static void main(String[] args){IEmployee programmer = new Programmer();Proxy.newProxyInstance(programmer.getClass().getClassLoader(),programmer.getClass().getInterfaces(),new ProductManager());}
}
接口实现式
public interface Mapper {Object selectById(Integer id);
}
public class SessionManager {public static <T>T getMapper(Class<T> mapper) {T t = (T)Proxy.newProxyInstance(SessionManager.class.getClassLoader(), new Class[]{mapper}, (proxy,method,args)-> {if("selectById".equals(method.getName())){return "Arthur is " + args[0];}return null;});return t;}public static void main(String[] args){PersonMapper personMapper = SessionManager.getMapper(PersonMapper.class);System.out.println(personMapper.selectById(2));}
}
AOP
public interface IAdvice {void exec();
}
public class BeforeAdivice implements IAdvice{@Overridepublic void exec() {System.out.println("执行前置通知");}
}
public class AfterAdvice implements IAdvice{@Overridepublic void exec() {System.out.println("执行前置通知");}
}
public class ProxyManager implements InvocationHandler {private Object object;public ProxyManager(Object object) {this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {IAdvice beforeAdvice = new BeforeAdivice();beforeAdvice.exec();method.invoke(object, args);IAdvice afterAdvice = new AfterAdvice();afterAdvice.exec();return null;}public static void main(String[] args) {Test test = new TestImpl();Test proxy = (Test) Proxy.newProxyInstance(ProxyManager.class.getClassLoader(), new Class[]{Test.class}, new ProxyManager(test));proxy.show();}
}
public interface Test {void show();
}
public class TestImpl implements Test{@Overridepublic void show() {System.out.println("这是一个悲惨的方法");}
}
更多推荐
浅谈代理模式(一)
发布评论