spring AOP学习笔记

Spring AOP

AOP

  • 静态AOP=》直接对字节码进行更改,对切面做任何的更改都需要重新编译程序
  • 动态AOP=》在运行时织入,性能不如静态AOP

Spring AOP包含

  • AOP 内核
  • 一组框架服务

AOP Alliance是由多个开源AOP共同制定的一组AOP标准接口
AOP的流程:

  • 创建切面类
  • 创建ProxyFactory实例
  • 调用addAdvice(),为实例添加切面类
  • 使用setTarget()为代理实例添加目标类
  • 使用getProxy()得到代理后的目标实例
  • 调用实例方法

AOP的优点:可以在不考虑AOP的情况下创建了类,也可以为任何类提供通知
Spring AOP中不能通知final修饰的类,因为他们不能被覆盖
Spring AOP的架构:
spring AOP的核心是基于代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GjwlI94y-1583159134320)(en-resource://database/1164:1)]

在spring中有两个代理实现

  • JDK代理实现(动态代理,只支持代理接口)
  • CGLIB代理

在spring中,连接点只支持方法调用,在实际使用中,方法调用时最有用的。
创建的通知类型有:

  • 前置通知:继承MethodBeforeAdvice,实现before()方法。通过使用前置通知,可以在连接点执行之前完成自定义处理。因为Spring 的 连接点就是方法调用,所以通常允许方法执行之前执行预处理。虽然前置通知可以完全访问方法调用的目标以及传递给方法的参数,但却无法控制方法本身的执行。如果前置通知抛出异常,那么拦截器链(以及目标方法)的进一步执行将被中止, 并且异常将传回拦截器链
  • 后置返回通知,继承AfterReturnAdvice,在连接点的方法调用完成执行并返回一个值后执行后置返回通知。后置返回通知可以访问方法调用的目标、传递给方法的参数以及返回值。由于方法在调用后置返回通知时已经执行, 因此根本无法控制方法调用。如果目标方法抛出异常,则不会运行后置返回通知,并且异常将照常传回调用堆栈
  • 环绕通知,继承MethodInterceptor,在Spring 中,环绕通知使用方法拦截器的AOP ALLiance 标准进行建模。环绕通知允许在方法调用之前和之后执行, 并且可以控制允许进行方法调用的点。如果需要,可以选择完全绕过方法,从而提供自己的逻辑实现
  • 异常通知
  • 后置返回通知无法修改返回值,但是环绕通知允许修改返回值

切入点

建议避免将硬编码的方法检查放入通知,尽可能的使用切入点通知对目标方法的适用性。
切入点实现了Pointcut接口,包含了getClassFilter()和getMethodMatcher(),Spring 支持两种类型的MethodMatcher一静态和动态MethodMatcher。

在spring中提供了8个Pointcut接口,2个用于创建静态和动态的切入点的抽象类,以及6个具体类。

  • StaticMethodMatcherPointcut,用于创建静态的切入点
  • DynamicMethodMatcherPointcut,用于创建动态的切入点
  • NameMatchMethodPointcut,使用简单的名字匹配,不考虑方法的签名
  • JdkRegexpMethodPointcut,使用正则匹配
  • AspectJExpressionPointcut,使用AspectJ匹配
  • AnnotationmatchingPointcut,使用注解匹配
  • ControlFlowPointcut,控制流切入点
  • ComposePointcut,组合切入点

在使用Pointcut之前,需要先实现PointcutAdvisor接口

代理

代理的核心是拦截方法调用,并在必要时执行适用于特定方法的通知链。
1、JDK动态代理
jdk代理实spring中基本的代理类型,代理过程:

  • 所有的方法被JVM拦截并路由到代理的invoke()方法
  • 有invoke()方法确定是否通知有关方法(根据切入点制定的规则)
  • 如果通知,则通过使用反射调用通知链,然后调用方法本身

在调用invoke()之前, JDK 代理无法区分被通知方法和未被通知方法。这意味着对于代理上的未被通知方法,invoke()方法仍然会被调用,所有检查仍然会执行,并且仍然可以通过使用反射进行调用会导致运行时开销,即使代理不会执行额外的处理,而只是通过反射调用未被通知的方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KfdlvD2P-1583159134339)(en-resource://database/1166:1)]

2、CGLIB代理

CGLIB 会为每个代理动态生成新类的字节码,并尽可能重用己生成的类,因此代理类型是目标对象的子类。
当首次创建CGLIB 代理时, CGLIB 会询问Spring 如何处理每个方法,CGLIB 代理可以确定一个方法是否返回代理: 如果不返回,则允许直接调用方法调用,从而进一步减少运行时间开销。
还以不同于JDK 代理的方式处理固定通知链。固定通知链是在代理生成后不会更改的,从而减少执行通知链的运行时间开销。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uVDRNAQq-1583159134341)(en-resource://database/1168:1)]

决定使用哪个代理通常很容易。CGLIB 代理可以代理类和接口,而JDK 代理只能代理接口。在性能方面,除非在冻结模式下使用CGLIB , 否则JDK 和CGLIB 标准模式之间没有显著差异(至少在运行被通知和未被通知方法时没有显著差异)。在这种情况下,通知链不能更改且CGLIB 在冻结模式下会进行进一步优化。当需要代理类时, CGLIB代理是默认选择,因为它是唯一能够生成类代理的代理。如果想要在代理接口时使用CGLIB 代理,必须使用setOptimize()方法将ProxyFactory 中的optimize 标志的值设置为true。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值