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