代理模式

    科技2022-08-21  114

    何为代理模式? 代理模式是通过创建一个代理对象,用这个代理对象去代表真实的对象,客户端得到这个代理对象这个,对客户端并没有什么影响,就像得到真实的对象来使用

    代理分为静态代理和动态代理,我们先来看看静态代理,来一个租房的案例 静态代理的角色分析:

    抽象角色:一般用接口或者抽象类来扮演真实角色:被代理的角色代理角色:代理真实角色,一般会添加一些附属操作客户:访问代理对象 //抽象的角色 public interface Rent{ void rent(); } //真实角色 public class Host implements Rent{ public void rent(){ System.out.println("房东出租房子") } } //代理角色 public class Proxy implements Rent{ private Host host; public Proxy(Host host){ this.host=host; } public void rent(){ seeHouse(); host.rent(); fare(); } //看房-----中介自有的方法,房东没有 public void seeHouse(){ System.out.println("中介带你看房"); } //收中介费-----中介自有的方法,房东没有 public void fare(){ System.out.println("收中介费"); } } //客户 public class Client{ public static void main(String[] args){ Host host=new Host(); host.rent(); //传统情况下,我们直接找房东租房 } } //使用代理模式 public class Client{ public static void main(String[] args){ Host host=new Host(); //代理,中介帮房东出租房子,代理角色一般会有附属操作 Proxy proxy=new Proxy(host); //你不用面对房东,直接找中介租房 proxy.rent(); } }

    使用代理模式有哪些好处呢?

    可以使真实角色的操作更加纯粹,不用去关注一些公共的业务公共交给代理角色,实现业务分工公共业务发生扩展的时候,方便集中管理

    使用代理模式缺点: 一个真实角色就需要代理对象,耗费资源

    静态代理加深理解,用比较常见的Service层来讲解

    //抽象角色 public interface UserService{ public void add(); public void delete(); public void update(); public void query(); } //真实对象 publci class UserServiceImpl implements UserService{ public void add(){ System.out.println("增加了一个用户"); } public void delete(){ System.out.println("删除了一个用户"); } public void update(){ System.out.println("更新了一个用户"); } public void query(){ System.out.println("查询了一个用户"); } } //代理类,在不改变原来的业务代码基础上,增加功能 public class UserServiceProxy implements UserService{ public void add(){ log("add"); System.out.println("增加了一个用户"); } public void delete(){ log("delete"); System.out.println("删除了一个用户"); } public void update(){ log("update"); System.out.println("更新了一个用户"); } public void query(){ log("query"); System.out.println("查询了一个用户"); } publci void log(String msg){ System.out.println(msg); } } //客户 public class Client{ UserService userService=new UserServiceImpl(); userService.add(); //传统调用方法 } public class Client{ UserService userService=new UserServiceProxy(); userService.add(); //代理对象调用方法 }

    使用 代理模式后我们可以在不改变原有基础的逻辑上,增加了一个打印日志的功能

    接下来说说动态代理,动态代理和静态代理中的角色是一样的,只不过区别是,动态代理中的代理类是动态生成的,而不是像静态代理中有开发人员自己编写。动态代理主要分为两大类,一个是基于接口的动态代理,也就是我们所说的JDK的动态代理;另一类是基于类的动态代理,也就是cglib。 我们都知道SpringAOP的底层就是动态代理,没有默认实现的方式,具体使用的那种动态代理方式,主要还是看代理的是类还是接口。是接口的话,使用的就是JDK的动态代理,是类的话,使用的就是cglib的动态代理

    还是再来看看刚刚租房的案例,使用动态代理是如何实现的吧

    //抽象的角色 public interface Rent{ void rent(); } //真实角色 public class Host implements Rent{ public void rent(){ System.out.println("房东出租房子") } } //代理处理器 public class ProxyInvocationHandle implements InvocationHandler{ //被代理的接口,抽象角色 private Rent rent; public void setRent(Rent rent){ this.rent=rent; } //生成代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); } //处理代理实例,并且返回结果 public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{ //动态代理的本质,基于反射实现 seeHouse(); Object result=method.invoke(rent,args); fare(); return result; } public void seeHouse(){ System.out.println("中介带看房子"); } public void fare(){ System.out.println("收中介费"); } } //客户类 public class Client{ public static void main(String[] args){ //真实角色 Host host=new Host(); //代理处理器 ProxyInvocationHandler pih=new ProxyInvocationHandler(); //通过代理处理器处理要调用的接口对象 pih.setRent(host); Rent proxy=(Rent) pih.getProxy(); proxy.rent(); } }

    自己写动态代理的话,我们需要去实现一个InvocationgHandler接口,动态代理的本质是反射。

    //抽象角色 public interface UserService{ public void add(); public void delete(); public void update(); public void query(); } //真实角色 public class Host implements Rent{ public void rent(){ System.out.println("房东出租房子") } } //代理处理器 public class ProxyInvocationHandle implements InvocationHandler{ //被代理的接口,抽象角色 private Object target; public void setTarget(Object target){ this.target=target; } //生成代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } //处理代理实例,并且返回结果 public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{ //动态代理的本质,基于反射实现 log(method.getName); Object result=method.invoke(target,args); return result; } public void log(String msg){ System.out.println(msg+"方法执行了"); } } public class Client{ public static void main(String[] args){ //真实角色 UserServiceImpl userServiceImpl=new UserServiceImpl(); //代理处理器 ProxyInvocationHandler pih=new ProxyInvocationHandler(); pih.setTarget(userServiceImpl); UserService proxy=(UserService)pih.getProxy(); proxy.query(); } }

    动态代理的好处: 可以使真实对象的操作更加纯粹,不用去关注一些公共的业务 公共交给代理角色,实现业务分工 公共业务发生扩展的时候,方便集中管理 一个动态代理类代理一个接口,一般就是对应一类的业务 一个动态代理类可以代理多个类,不像静态代理那样,一个代理类代理一个角色

    Processed: 0.015, SQL: 9