Spring学习笔记(八)静态代理与动态代理

静态代理设计模式

为什么需要静态代理设计模式

  1. JavaEE分层开发,Service层是最主要的
  2. Service层包含了哪些代码?
    Spring学习笔记(八)静态代理与动态代理_第1张图片
  3. 额外功能书写在Service层中好不好?
    设计者:不希望有额外功能
    调用者:有这些额外功能
    现实中典型案例:租房
    Spring学习笔记(八)静态代理与动态代理_第2张图片

代理设计模式

  1. 概念:通过代理类,为原始类增加额外的功能。
  2. 好处:利于原始类(目标类)的维护
  3. 目标类/原始类:房东,业务类,核心功能。
  4. 目标方法/原始方法:原始类目标类中的方法(核心功能)
  5. 额外功能:附加功能,日志,事务,性能。代理类来负责。
  6. 代理类开发核心要素
    代理类=目标类+额外功能+实现原始类相同的接口。
    代理类要迷惑用户,认为自己调用了目标类,所以接口和实现的方法要相同。通过实现接口完成。
    Spring学习笔记(八)静态代理与动态代理_第3张图片

静态代理存在的问题

静态代理的意思是要为每一个原始类都要手工编写一个代理类。
1. 静态类文件数量过多,不利于项目管理。
2. 如果想对日志格式修改,需要对每个类都进行修改,额外功能维护性差,修改复杂。
好处:确实可以提供额外功能
缺点:修改维护太差。

spring动态代理开发

概念:和静态代理的目的差不多

动态代理开发步骤

  1. 创建原始对象
  2. 额外功能。spring的MethodAdvice接口
    额外的功能书写在接口实现的before方法中,运行在原始方法运行之前执行。
    Spring学习笔记(八)静态代理与动态代理_第4张图片
    配置文件:
    在这里插入图片描述
  3. 定义切入点
    切入点:额外功能加入的位置
    目的:由程序员根据自己的需要,决定额外功能加入给哪个原始方法。
    通过配置文件配置切入点。
    在这里插入图片描述
  4. 组装(2,3整合)
    把额外功能整合到aop的标签中,指定pc切入点切入。
    Spring学习笔记(八)静态代理与动态代理_第5张图片
  5. 调用
    获得spring工厂创建的动态代理对象,并进行调用。
    1. spring工厂通过原始id获得的是代理对象。
    2. 获得代理对象后,可以通过声明接口类型接收(因为代理对象实现了和原始对象一样的接口)

动态代理类细节Fenix

1.动态代理类在哪里?
spring框架在运行时,通过动态字节码技术,在JVM创建的,运行在JVM内部,等程序结束后,会和JVM一起消失。
动态字节码技术:通过第三方动态字节码框架,在JM中创建对应类的字节码。
Spring学习笔记(八)静态代理与动态代理_第6张图片
结论:动态代理不需要定义类文件,都是JVM运行过程中动态创建的,不会造成类文件数量过多,影响项目管理的问题。
2. 动态代理简化代码开发。
额外功能不变的前提下,只要更改/增加目标对象即可。
3. 动态代理的维护性大大增加了。
替换额外功能,只需要改配置文件。
所有的方法都会随之替换

spring动态代理详解

  1. MethodBeforeAdvice before参数详解
    method:额外功能所增加给的方法。
    object[]:额外方法对应的参数。
    object:代表原始对象
    Spring学习笔记(八)静态代理与动态代理_第7张图片
  2. before方法的三个参数在实战中,如何使用
    不一定都会使用,甚至都不使用。
  3. MethodInterceptor(方法拦截器)
    前,后,前后都可以实现。
    额外功能写在invoke方法,可以加在原始之前,之后,之前和之后。,

返回值是原始方法的返回值,通过proceed函数调用原始方法。
Spring学习笔记(八)静态代理与动态代理_第8张图片
事务是运行在之前之后,最典型的案例
Spring学习笔记(八)静态代理与动态代理_第9张图片
额外功能运行在原始方法抛出异常的时候
Spring学习笔记(八)静态代理与动态代理_第10张图片
MethodInterceptor影响原始方法的返回值
不直接返回原始方法的返回值。(很少干预原始方法的返回值)
实际开发中用Interceptor更多一些(拦截器)

切入点详解

  1. 决定了额外功能加入的位置(方法)
  2. 在这里插入图片描述
  3. execution(* *(…))的含义:第一个星 是修饰符返回值,表示没有要求,第二个星表示方法名没有要求求,括号里的点点表示对参数没有要求(参数有没有,有几个都行,什么类型都行)
    例如定义 *login(String,String)表示两个字符串类型的login函数作为切入点。
    注意:
  4. 非java.lang包中的类型,必须要写全限定类名
    在这里插入图片描述
  5. 对于参数的限制,…可以和具体参数类型连用
    在这里插入图片描述

问题:上面的切入点并不精准

同包下不同类的多个方法,可能都被同一个表达式匹配。
Spring学习笔记(八)静态代理与动态代理_第11张图片
精准的限定
Spring学习笔记(八)静态代理与动态代理_第12张图片
如果有多个login方法就需要精准的限定
在这里插入图片描述

类切入点

Spring学习笔记(八)静态代理与动态代理_第13张图片
如果在所有包的这个类都切入
就把包换成*,但是只适用于上面只有一层包。
如果有多级包,要加点点。
在这里插入图片描述

包切入点

关注包,切入后包中所有类和方法都会加入额外功能
语法1:必须在包中,不能再子包中。
在这里插入图片描述
语法2:点点 代表当前包及其子包。
在这里插入图片描述
包切入点是后续实战中更具实战价值的

切入点函数

切入点函数:用于执行切入点表达式

  1. execution:最重要的切入点函数,功能最全。
    可以执行:方法切入点表达式,类切入点表达式,包切入点表达式
    弊端:书写麻烦。
    注意:其他的切入点函数,功能完全一致,只是简化execution。
  2. args:作用:用于方法参数的匹配
    切入点:例如方法参数必须是两个字符串类型的参数
    args(String,String)
    不关注包、类、函数,只关注参数。
  3. within
    作用:主要用于进行类、包切入点表达式的匹配。
    Spring学习笔记(八)静态代理与动态代理_第14张图片
  4. @annotation
    作用:为具有特殊注解的方法加入额外功能
    注解可以自定义注解
    在这里插入图片描述
  5. 切入点函数的逻辑运算
    多个切入点函数一起配合工作,完成更复杂的需求。
    and 操作和or操作
    在这里插入图片描述
    与操作不能用于同种类型的切入点函数。
    例如:
    在这里插入图片描述
    但是这个实际上是一个或的关系,与操作的意思是同时满足。不可能同时满足两个名字。
    在这里插入图片描述

总结

Spring学习笔记(八)静态代理与动态代理_第15张图片
作用就是 通过代理类为原始类增加额外功能
好处就是利于原始类的维护

你可能感兴趣的:(后端开发,设计模式,spring,java,编程语言)