浅谈代理模式(一)

代理模式基础

代理模式基础

  • 代理模式是在框架设计中经常使用的一种设计模式。

首先代理模式,可以分为两种,一种是静态代理,一种是动态代理。

  • 代理模式属于结构型设计模式。
  • 它的作用是为其他对象提供一层代理以控制对类的访问,当我们无法直接访问某一个类时可使用代理模式作为中介。

两种代理从虚拟机加载类的角度来讲,本质上都是一样的,都是在原有类的行为基础上,加入一些多出的行为,甚至完全替换原有的行为。

  • 代理类和委托类必须实现同一接口。

动态代理有一个强制性要求,就是被代理的类必须实现了某一个接口,或者本身就是接口,就像我们mybatis中的Mapper。

  • 代理模式的优点 :可以在不修改委托类的情况下,为委托类提供新的功能,符合开闭原则。
  • 代理模式的应用场景 :
    1. 为委托类添加统一处理,例如Spring的AOP。
    2. 提供统一快捷的请求访问,例如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("这是一个悲惨的方法");
    }
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值