代理模式

本文介绍了代理模式的概念,通过租房案例详细解释了静态代理的实现,展示了如何通过代理对象隔离公共业务和真实对象。接着讨论了动态代理,指出其在不修改原有代码的基础上增加功能的优势,如Spring AOP中的应用。动态代理分为基于接口的JDK动态代理和基于类的cglib动态代理,并举例说明了其实现方式。
摘要由CSDN通过智能技术生成

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

代理分为静态代理和动态代理,我们先来看看静态代理,来一个租房的案例
在这里插入图片描述
静态代理的角色分析:

  • 抽象角色:一般用接口或者抽象类来扮演
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,一般会添加一些附属操作
  • 客户:访问代理对象
//抽象的角色
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();
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值