首页 > 其他分享 >spring学习日记-day5-代理模式

spring学习日记-day5-代理模式

时间:2024-09-01 12:21:59浏览次数:15  
标签:对象 spring travel day5 代理 接口 日记 void public

一、学习目标

        代理模式是一种常用的设计模式,它主要用于在不修改原有对象代码的情况下,通过引入一个代理对象来控制对原有对象的访问,从而增强原有对象的功能。代理模式主要分为两种:静态代理和动态代理。尽管Spring框架本身更多地利用了动态代理来实现其功能,但理解静态代理是理解Spring代理机制的基础

  代理模式(Proxy Pattern)是程序设计中的一种重要设计模式,属于结构型设计模式。它主要通过为其他对象提供一个代理以控制对这个对象的访问,从而在客户端和目标对象之间起到中介的作用。  

        代理模式主要包含以下三个角色:

  1. 抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
  2. 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  3. 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用

        

        代理模式主要分为以下几种类型:

  1. 静态代理:在代码编译阶段就已经生成了代理类,代理类需要实现与目标对象相同的接口。静态代理在不修改目标对象的前提下对目标对象的方法进行增强,但需要为每个目标对象创建一个代理类,导致系统中类的数量增加,维护成本较高。
  2. 动态代理:在程序运行时,通过反射机制动态生成的代理类。Java中可以使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。动态代理可以为多个目标对象创建一个代理类,减少了类的数量,并且更加灵活地处理不同的情况。但由于使用了反射机制,性能相对静态代理略低。
  3. CGLIB代理:CGLIB代理是通过继承目标对象的方式来创建代理类。它是第三方库(如Spring AOP)常用的一种代理方式,适用于没有实现接口的类。CGLIB代理不需要目标对象实现接口,可以代理任何类,但由于采用了继承的方式,目标类不能是final类,代理类也不能是final方法。相对于JDK动态代理,CGLIB代理的性能较高,但由于使用了字节码生成技术,可能会增加复杂性。

         优点

  1. 职责清晰:真实角色只关注实际的业务逻辑,而代理对象负责非业务逻辑的操作,使得编程更加简洁清晰。
  2. 降低耦合度:代理模式在一定程度上降低了系统的耦合度,提高了系统的扩展性。
  3. 保护作用:代理对象在客户端和目标对象之间起到中介的作用,可以保护目标对象不被直接访问。
  4. 增强功能:代理模式可以在不改变原始对象的情况下,为其增加额外的功能,如日志记录、权限校验等。

二、静态代理

1.定义一个接口,目标类和代理类都将实现这个接口

public interface Travel {
    //实现旅游功能
    public void travel();
}

2.目标类实现上述接口,定义业务逻辑

public class Spot implements Travel{
    //spot为旅游目的地,实现旅游功能
    public void travel() {
        System.out.println("接待游客");
    }
}

3代理类实现上述接口,并持有目标类的一个实例

public class Proxy implements Travel{
    private Spot spot;

    public Proxy(Spot spot) {
        this.spot = spot;
    }

    public void travel() {
        plan();
        ticket();
        spot.travel();
    }
    
    public void plan(){
        System.out.println("做攻略");
    }
    public void ticket(){
        System.out.println("订票");
    }
}

4.客户通过代理类来调用目标类

public class Client {
    public static void main(String[] args) {
        Spot spot=new Spot();
        Proxy proxy=new Proxy(spot);
        proxy.travel();
    }

}

5.优缺点

优点

1.实现简单,易于理解。

2.可以在不修改目标对象的前提下扩展目标对象的功能。

缺点

1.如果目标对象很多,需要为每一个目标对象创建一个代理类,这会导致类爆炸,增加系统的复杂度和维护成本。

2.如果接口增加方法,则目标对象和代理类都需要修改,这违反了开闭原则

三、动态代理

1.定义一个接口。

public interface Travel {
    //实现旅游功能
    public void travel();
}

2.创建一个实现了该接口的目标类。

public class Spot implements Travel{
    public void travel() {
        System.out.println("接待游客");
    }
}

3.创建一个实现了InvocationHandler接口的代理类,在invoke方法中编写增强逻辑。

// 定义一个实现了InvocationHandler接口的类,用于创建动态代理对象  
public class ProxyInvocationHandler implements InvocationHandler {  
    // 持有被代理对象的引用  
    private Travel travel;  
  
    // 设置被代理对象的方法  
    public void setTravel(Travel travel) {  
        this.travel = travel;  
    }  
  
    // 获取动态代理对象的方法  
    // 这里需要注意,获取代理对象的类加载器应该是被代理对象的类加载器,而不是ProxyInvocationHandler的类加载器  
    public Object getProxy(){  
        // 使用Proxy类的newProxyInstance方法创建代理对象  
        // 第一个参数:类加载器,加载代理类的ClassLoader  
        // 第二个参数:被代理对象实现的接口数组,代理类需要实现这些接口  
        // 第三个参数:实现了InvocationHandler接口的处理器对象  
        return Proxy.newProxyInstance(  
            this.travel.getClass().getClassLoader(), // 使用被代理对象的类加载器  
            travel.getClass().getInterfaces(), // 获取被代理对象实现的接口数组  
            this // 将当前对象作为InvocationHandler  
        );  
    }  
  
    // 实现InvocationHandler接口的invoke方法  
    // 该方法会在代理对象调用方法时被自动调用  
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        // 在调用被代理对象的方法之前,执行一些前置操作,如做攻略和订票  
        plan();  
        ticket();  
  
        // 调用被代理对象的方法,使用反射机制  
        // method.invoke(被代理对象, 参数数组)  
        Object result = method.invoke(travel, args);  
  
        // 返回被代理对象方法的执行结果  
        return result;  
    }  
  
    // 前置操作:做攻略  
    public void plan(){  
        System.out.println("做攻略");  
    }  
  
    // 前置操作:订票  
    public void ticket(){  
        System.out.println("订票");  
    }  
}

4.使用Proxy.newProxyInstance方法创建代理对象。

 public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                travel.getClass().getInterfaces(), this);
    }

5.通过代理对象调用目标方法,自动执行增强逻辑。

public class Client {
    public static void main(String[] args) {
        Spot spot=new Spot();
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTravel(spot);
        Travel proxy=(Travel)pih.getProxy() ;
        proxy.travel();
    }

}

6.优缺点

优点

解耦:将切面逻辑与业务逻辑分离,降低了系统的耦合度。

灵活:可以在不修改目标对象代码的情况下,为目标对象添加额外的功能或逻辑。

易于维护:切面逻辑可以集中管理,便于维护和升级。

缺点

性能开销:动态代理的创建和调用过程中存在反射或字节码生成等开销,可能会影响系统性能。

限制:JDK动态代理只能代理实现了接口的类;CGLIB动态代理不能代理final修饰的类和方法。

标签:对象,spring,travel,day5,代理,接口,日记,void,public
From: https://blog.csdn.net/2301_79789506/article/details/141317970

相关文章

  • springboot+vue+mybatis计算机毕业设计飞机订票系统+PPT+论文+讲解+售后
    快速发展的社会中,人们的生活水平都在提高,生活节奏也在逐渐加快。为了节省时间和提高工作效率,越来越多的人选择利用互联网进行线上打理各种事务,然后线上管理系统也就相继涌现。与此同时,人们开始接受方便的生活方式。他们不仅希望页面简单大方,还希望操作方便,可以快速锁定他们需......
  • 基于Springboot快递物流仓库管理系统【附源码+文档】
    ......
  • 【有源码】基于springboot+vue的高校大学生创新创业学分管理系统的设计与实现
    注意:该项目只展示部分功能,如需了解,文末咨询即可。本文目录1.开发环境2系统设计2.1设计背景2.2设计内容3系统展示3.1功能展示视频3.2前台页面3.3后台页面4更多推荐5部分功能代码1.开发环境开发语言:Java采用技术:sprngboot、vue数据库:MySQL开发环境:In......
  • 开学第一周9.1周日学习日记
    算法cf1989ABCDhttps://codeforces.com/contest/1989B最长公共子序列 //相当于枚举以b[i]为起点遍历a的最长公共子序列 //因为是子序列所以abacccab即使后面先取了第一个a也不影响最长长度#include<bits/stdc++.h>usingnamespacestd;voidsolve() { stringa......
  • 图书系统的创建(三)——日记
    在写完操作后,我们可以创建User用户包,在这个包内我们要建立管理员(librarian)和普通成员(normal)两个类,对于用户的创建我认为有几个值得注意的点:1.菜单框架同样的,我们可以创建一个共同特征user父类,我们可以在里面定义name变量和构造方法。在两个子类中,我们肯定一个菜单menu去给出......
  • SpringBoot中,启动A服务,naocs却注册B服务,解决思路。
     今天遇到了一个令我非常费解的报错,我明明启动的是auth服务,但是nacos愣是给我注册的patient服务,下面看看解决思路(虽然我这个问题很乌龙,但如果真的是你的配置有问题,那么这篇文章也是可以帮助到你。)目录1、控制台输出2、nacos配置 3、本地yml配置 1、控制台输出1.首......
  • 处理springboot使用fastJson浏览器调用接口正常返回数据却中文乱码的问题
    处理springboot使用fastJson浏览器调用接口正常返回数据却中文乱码的问题这属于fastJson的一个bug只需要像下面这样操作就可以了@Bean//使用Bean入fastJsonHttpllessageConvertpublicHttpMessageConverterfastJsonHttpMessageConverters(){//需婴定义......
  • 推荐一个开源免费的 Spring Boot 实战项目
    最近由于笔者所在的研发集团产品需要,需要支持高性能的大文件(大都数是4GB以上)的http上传,并且要求支持http断点续传。笔者在以前的博客如何实现支持大文件的高性能HTTP文件上传服务器已经介绍了实现大文件上传的一些基本概念,其实非常简单,这里在简要归纳一下,方便记忆:服务器端由C语言......
  • 【项目日记】高并发内存池---实现中心缓存
    年少的梦啊,有些很幸运地实现了,有些被遗忘在了风中---董卿---高并发内存池---实现中心缓存1整体理念2SpanList的实现3CentralCache的实现4请求内存联动1整体理念实现中心缓存之前,我们先理解中心缓存需要做那些事情,具有哪些特性?我们把中心缓存的功能......
  • springboot+vue+mybatis计算机毕业设计电影影评的垂直搜索引擎+PPT+论文+讲解+售后
    近年来,科技飞速发展,在经济全球化的背景之下,大数据将进一步提高社会综合发展的效率和速度,大数据技术也会涉及到各个领域,而爬虫实现网站数据可视化在网站数据可视化背景下有着无法忽视的作用。管理信息系统的开发是一个不断优化的过程,随着网络大数据时代的到来,管理信息系统与大......