Spring-代理模式

用一个租房子的案例来讲解代理模式的概念

  • 房东要出租房子,他把这个事情交给了中介,中介帮他出租房子,租客原本要找房东租房子,但是现在只需要找中介即可。

  • 这样做有什么好处呢?我们把中介 看成一个 ,把房东 看成一个接口,房东只有一个业务,就是出租房子,当中介拿到了房东的接口,也能实现出租房子的业务,但是中介还能有其他业务,比如签合同,看房等等,这些业务是房东没有的。
    在上面的例子里:

  • 房东----真实角色

  • 中介----代理角色
    代理模式的好处:

  • 可以使真实角色的操作更加存粹,不用关注公共业务

  • 公共业务就交给代理角色,实现了业务的分工

  • 把增添新的业务交给代理类,不会让原有代码受到更改

案例如下:

接口:

实现类:

现在我想加一个日志功能 ,但是为了保护原有代码的完整性 ,不能在原来的代码里增加功能,这个时候就可以使用代理类 ,我们在代理类中实现日志功能,这样就避免了修改原有代码。

代理类:

以上所展现的方式是静态代理,每有一个公共接口就要创建一个与之对应的代理类,这样太麻烦了,有没有能自动生成代理类的方法呢?这时,就有了动态代理 模式,我们不需要手动的创建Proxy代理类,只需调用固定的方法,就可以实现自动生成代理类

java 复制代码
public class ProxyInvocationHandler implements InvocationHandler {


    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    //InvocationHandler handler = new MyInvocationHandler(...);
    //Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler);

    //得到代理类
    //参数用了反射
    //第一个参数:类加载器(用来创建代理类)
    //第二个参数:公共接口(以租房为例的话,就是rent这个接口,也就是代理类要实现的业务)
    //第三个参数:invocationHandler,这里用this代替
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }


    //处理代理实例,并返回各个方法的结果
    //代理实例新增的业务,放进这个方法中就可以被处理并返回
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //用来调用类中的方法(其本质是反射,当我们拿到代理类之后,要通过反射去调用原来公共接口的方法)
        //第一个参数:原来的公共接口
        //第二个参数:将原来的接口里的方法参数化了,我们可以理解成把参数名存进数组里依次调用
        Object result = method.invoke(target, args);
        log();
        return result;
    }

    //怎么给代理类新增业务,将写好的方法扔进invoke方法中即可
    public void log(){
        System.out.println("接口新增业务被调用");
    }
}

测试类:

java 复制代码
public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();

        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        //创建一个等会要被代理的接口
        pih.setTarget(userService);
        //注意这里转型的是UserService接口而不是UserServiceImpl实现类
        UserService proxy = (UserService) pih.getProxy();

        proxy.add();
        proxy.delete();
    }
}

我们可以把上面的这个类看成一个自动生成代理类工具类,只需要调用这个类中的方法,就可以实现动态代理

相关推荐
讨厌吃蛋黄酥1 分钟前
前端跨域难题终结者:从JSONP到CORS,一文搞定所有跨域问题!
前端·javascript·后端
华仔啊2 分钟前
Java序列化详解:什么情况下必须用它?
java
cxyxiaokui0015 分钟前
Exception和Error:一场JVM内部的“家庭伦理剧”
后端·面试
义达6 分钟前
Django环境下使用wsgi启动MCP服务
后端·django·mcp
用户4099322502127 分钟前
如何在FastAPI中巧妙实现延迟队列,让任务乖乖等待?
后端·ai编程·trae
码事漫谈10 分钟前
为什么我们应该避免使用 abort、exit、getenv 和 system?
后端
码事漫谈12 分钟前
为什么动态内存分配在关键系统中被视为“不合规”?
后端
_風箏12 分钟前
Ollama【部署 02】Linux本地化部署及SpringBoot2.X集成Ollama(ollama-linux-amd64.tgz最新版本 0.6.2)
人工智能·后端·ollama
张同学的IT技术日记14 分钟前
详细实例说明+典型案例实现 对动态规划法进行全面分析 | C++
后端
小华同学ai18 分钟前
炸裂!Github 6000+ star 开源免费易用,支持1000+格式转换,值得收藏!
前端·后端·github