spring源码设计模式分析-代理设计模式(二)

简介: spring源码设计模式分析-代理设计模式(二)

昨天写的四种建造者的设计模式是在spring中用BeanDefinitionBuilder来动态构建bean定义对象时创建的在IOC容器中,所有的操作都是基于bean对象来操作的,在spring中用的是深拷贝的模式,spring中常用的设计模式是13种,还有一种设计模式是桥接的设计模式,主要用到泛型的会用到。

结构型设计模式:

1、代理设计模式:当我们看spring的aop的时候会用到代理设计模式,主要用来创建bean的代理对象的,因为aop的核心是进行横切,本质将bean定义的对象,然后创建一个代理对象,

来以偷听换玉的方式将bean的定义对象换成代理对象,然后这个容器种中bean本身的对象就不存在了,全部由代理对象来操作,@Autowired和@Resource在依赖注入的时候,全部注入的是aop代理对象,在代理设计模式中一种是jdk的,一种是cglib的,在spring中大多数都是cglib代理,代理就是代理别人的功能。

1.1、JdkDynamicAopProxy :jdk动态代理,用来创建接口代理对象

1.2、CglibAopProxy:动态代理,用来创建类的代理对象

静态代理:

①、首先创建一个接口:

  1. package com.weizhaoyang.proxy;

  2. /**
  3. * 业务服务接口
  4. */
  5. public interface DemoService{
  6. /**
  7.     * 业务服务demo
  8.     */
  9. publicString  demo();
  10. /**
  11.     * 业务服务2
  12.     */
  13. //public  void  demo2();
  14. }

②、创建一个实现类:

  1. package com.weizhaoyang.proxy;

  2. public class DemoServiceImpl implements  DemoService {
  3.    @Override
  4.    public String demo(String name) {
  5.        System.out.println("我需要记录日志");
  6.        return "weizhaoyang";
  7.    }
  8. }

创建一个静态代理的类:

  1. package com.weizhaoyang.proxy;

  2. /**
  3. * DemoService的静态代理
  4. *
  5. */
  6. public class DemoServiceStaticProxy implements DemoService {
  7.    //加一个属性DemoService,全部由代理类来控制掉,所以要依赖进来,也就是一种封装,只由代理类来控制
  8.    private DemoService demoService;
  9.    public DemoServiceStaticProxy(DemoService demoService){
  10.        this.demoService=demoService;
  11.    }

  12.    @Override
  13.    public String demo(String name) {
  14.        System.out.println("代理执行之前");
  15.        demoService.demo(name);
  16.        System.out.println("代理执行之后");
  17.        return "weizhaoyang";
  18.    }
  19. }

创建一个测试类:

  1. package com.weizhaoyang.proxy;

  2. public class DemoTest1 {

  3.        public static void main(String[] args) {
  4.            DemoService demoService= new DemoServiceImpl();
  5.            //创建一个代理类的对象,来把demoService这个对象给 控制住
  6.            DemoService  demoService2=new DemoServiceStaticProxy(demoService);
  7.            //然后再DemoService这个接口之上完成自己的功能
  8.            System.out.println(demoService2.demo("weizhaoyang"));


  9.    }
  10. }

运行的结果如下:

在Spring的ioc容器里面相当于用这个代理对象将DemoService对象全部替换掉了这就是代理对象能代替对象的根本原因

缺点:

1、静态代理必须要依赖原有的对象

2、每加一个需求都需要改三个地方,接口,实现类,代理类,不好维护。

在java中一个代理类只能控制一个行为

解决上面的缺点:

1、通过反射动态代理就是基于反射来操作的,通过Method来动态执行接口中所有的方法,就是把接口中的方法抽象成一个Method对象传进来操作,反射虽然效率不高,但是提高了代码的灵活性。

2、用jdk动态代理来实现,就是基于反射来实现的,让类来实现InvocationHandler,通过代理对象调用invoke方法

代码如下:首先提供一个抽象的业务接口,把这个接口可以当作成service,也可以当作成具体的对象。

  1. package com.weizhaoyang.proxy;

  2. /**
  3. * 业务服务接口
  4. */
  5. public interface DemoService{
  6. /**
  7.     * 业务服务demo
  8.     */
  9. publicString  demo();
       


  10. }

提供 一个实现类:我这个行为需要产生日志记录

  1. package com.weizhaoyang.proxy;

  2. public class DemoServiceImpl implements  DemoService {
  3.    @Override
  4.    public String demo(String name) {
  5.        System.out.println("我需要记录日志");
  6.        return "weizhaoyang";
  7.    }
  8. }

提供一个动态代理的类:

  1. package com.weizhaoyang.proxy;

  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.InvocationTargetException;
  4. import java.lang.reflect.Method;
  5. import java.lang.reflect.Proxy;
  6. import java.sql.SQLOutput;

  7. /**
  8. * InvocationHandler执行处理器
  9. */
  10. public class DemoServiceProxy implements InvocationHandler {
  11.    //依赖目标类
  12.    private DemoService demoService;
  13.    public DemoServiceProxy(DemoService demoService) {
  14.        this.demoService=demoService;
  15.    }
  16.    public  Object getProxy(){
  17.        return Proxy.newProxyInstance(DemoService.class.getClassLoader(),new Class[]{DemoService.class},this);
  18.    }
  19.    //通过反射委托调用执行invoke方法,代理方法
  20.    @Override
  21.    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  22.        //记录开始日志
  23.        System.out.println("方法执行前打印日志");
  24.        //开始执行方法,调用自己的方法
  25.        Object object= null;
  26.        try {
  27.            object = method.invoke(demoService,args);
  28.        } catch (RuntimeException e) {
  29.           e.getMessage();
  30.        }
  31.        //3、记录日志
  32.        System.out.println("方法执行后打印日志");
  33.        if(object.equals("weizhaoyang")){
  34.            System.out.println("方法返回值通知");
  35.            throw new RuntimeException("异常通知");
  36.        }
  37.        return object;
  38.    }
  39. }

写个测试类:

  1. package com.weizhaoyang.proxy;

  2. public class DemoTest1 {

  3.        public static void main(String[] args) {
  4.           /* DemoService demoService= new DemoServiceImpl();
  5.            //创建一个代理类的对象,来把demoService这个对象给 控制住
  6.            DemoService  demoService2=new DemoServiceStaticProxy(demoService);
  7.            //然后再DemoService这个接口之上完成自己的功能
  8.            System.out.println(demoService2.demo());
  9. */
  10.          //创建被代理对象
  11.            DemoService demoService=new DemoServiceImpl();
  12.           //创建代理的对象
  13.            DemoServiceProxy demoServiceProxy=new DemoServiceProxy(demoService);
  14.            //获取被代理的对象
  15.            DemoService service= (DemoService) demoServiceProxy.getProxy();
  16.           service.demo("weizhaoyang");
  17.    }
  18. }

运行的结果如下:

解释下、getProxy方法中的参数的作用:

方法中的参数:new Class[]{DemoService.class}:把接口当作参数传进去   this:代表传InvocationHandler对象, DemoService.class.getClassLoader():将类加载器传进来,类加载器可以自定义,防止在定义接口的时候防止不是默认的加载器来加载道jvm里面的,所以需要传classloader ,InvocationHandler通过它来做一个桥梁将代理类和被代理做一个组合起来,然后将代理类对象去执行invoke方法,来动态的去调用本身的方法。

总结:

1、spring的aop就是基于上面的本质来操作的,所以在aop之中有前置通知,和后置通知还有方法返回值(执行完成之后,方法返回值没有返回)之后通知,还有一种是抛异常通知,可以在返回值之后抛异常,而在spring中把这几个通知封装成了各个的接口,封装的接口的意义在于去扩展,环绕通知是针对上面的四种一整套,前置通知和后置通知只是针对于方法的执行前后,这是jdk的动态的一种思路。

2、下面的就称之为springAOP中的抽象为前置通知。

下面的就称之为springAOP中的抽象为后置通知。

下面的就称之为springAOP中的抽象为异常通知。

下面的就称之为springAOP中的抽象为方法的返回值通知。

这个就称之为springAOP连接点joinPoint

这个就是SpringAop中的切入点,每一个切入点通过连接点来进行切入

然后把切点和通知封装为切面对象advice,然后动态的去植入,这就是aop的流程。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
人工智能 Java Serverless
【MCP教程系列】搭建基于 Spring AI 的 SSE 模式 MCP 服务并自定义部署至阿里云百炼
本文详细介绍了如何基于Spring AI搭建支持SSE模式的MCP服务,并成功集成至阿里云百炼大模型平台。通过四个步骤实现从零到Agent的构建,包括项目创建、工具开发、服务测试与部署。文章还提供了具体代码示例和操作截图,帮助读者快速上手。最终,将自定义SSE MCP服务集成到百炼平台,完成智能体应用的创建与测试。适合希望了解SSE实时交互及大模型集成的开发者参考。
15638 60
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
440 16
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
455 0
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
625 0
|
设计模式 安全 Java
并发设计模式实战系列(12):不变模式(Immutable Object)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十二章,废话不多说直接开始~
363 0
|
11月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
512 1
|
设计模式 算法 Java
设计模式觉醒系列(04)策略模式|简单工厂模式的升级版
本文介绍了简单工厂模式与策略模式的概念及其融合实践。简单工厂模式用于对象创建,通过隐藏实现细节简化代码;策略模式关注行为封装与切换,支持动态替换算法,增强灵活性。两者结合形成“策略工厂”,既简化对象创建又保持低耦合。文章通过支付案例演示了模式的应用,并强调实际开发中应根据需求选择合适的设计模式,避免生搬硬套。最后推荐了JVM调优、并发编程等技术专题,助力开发者提升技能。
|
设计模式 算法 架构师
京东二面:说下spring中常用的设计模式? (一个 深入骨髓的答案, 面试官跪下了)
京东二面:说下spring中常用的设计模式? (一个 深入骨髓的答案, 面试官跪下了)
京东二面:说下spring中常用的设计模式? (一个 深入骨髓的答案, 面试官跪下了)