AOP与代理

Spring Aop源码阅读&循环依赖问题


什么是AOP

  • 再软件行业,Aop为Aspect Oriented Programming的缩写,意为:面向切面编程
  • AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型
  • 作用:再不修改【目标类代码】的前提下,可以通过AOP技术去【增强目标类的功能】。通过【预编译方式】或者【运行期动态代理】实现程序功能的统一维护的一种技术
    • 对目标类进行无感知的功能增强。
  • AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构
  • AOP最早由AOP联盟的组织提出的,制定了一套规范。Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范
  • 利用AOP可以对业务代码中【业务逻辑】和【系统逻辑】进行隔离,从而使得【业务逻辑】和【系统逻辑】直接的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

为什么使用AOP

业务层存在的问题:

需要改善的地方:

  1. 抽象共性代码(系统功能)
  2. 将代码职责分离(系统功能,业务功能)
  3. 保证代码的扩展性
  • 作用:
    AOP采取横向抽取机制,补充了传统纵向继承体系(OOP)无法解决的重复性代码优化(性能监视,事务管理,安全检测,缓存),将业务逻辑和系统处理的代码(关闭连接,事务管理,操作日志记录)解耦。
  • 优势:
    重复性代码被抽取处理之后,维护更加方便
    不想修改原有代码前提下,可以动态横向添加共性代码。

AOP相关术语介绍

  • Joinpoint(连接点)

  • Pointcut(切入点)

  • Advice(通知/增强)

  • Introduction(引介)

  • Target(目标对象)

  • Weaving(织入)

  • Proxy(代理)

  • Aspect(切面)

  • Advisor(通知面,顾问)

AOP实现只AspectJ(了解)

  • AspectJ是一个Java实现的AOP框架,它能够对java代码进行AOP编译(一般在编译器进行),让java代码局有AspectJ的AOP功能(当然需要特殊的编译器)
  • 可以这样说AspectJ是目前实现的AOP框架中最成熟,功能最丰富的语言。更幸运的是,AspectJ与Java程序完全兼容,几乎是无缝关联,因此对于有java编程基础的工程师,上手和使用都非常容易
  • 了解AspectJ应用到java代码的过程(这个过程称为织入),对于织入这个概念,可以简单理解为aspect(切面)应用到目标函数(类)的过程
  • 对于织入这个过程,一般分为静态织入和动态织入,动态织入的方式是在运行时动态将要增强的代码织入到目标类中,这样往往是通过动态代理技术完成的,如Java JDK的动态代理(Proxy,底层通过反射实现)或者CGLIB的动态代理(底层通过继承实现),Spring Aop采用的就是基于运行时增强代理技术
  • ApectJ采用 的就是静态织入的方式,AspectJ主要采用的是编译器织入,在这个期间使用AspectJ的acj编译器(类似javac)把aspect类编译成class字节码后,在java目标类编译时织入,即先编译aspect类再编译目标类。

AOP实现之Spring Aop(了解)

实现原理分析
  • Spring AOP是通过动态代理技术实现的
  • 而动态代理是基于反射设计的。
  • 动态嗲了技术的实现方式有俩种:基于接口的JDK动态代理和基于继承的CGLIB动态代理
JDK动态代理

目标对象必须实现接口

Cglib动态代理
  • 目标对象不需要实现接口
  • 底层是通过继承目标对象产生代理子对象(代理子对象中继承了目标对象的方法,并可以对该方法进行增强)

ASM API使用

使用
  • 其实现ProxyFactoryBean创建
  • 使用aop:advisor定义通知器的方式实现AOP则需要通知类实现Advice接口
  • 增强(通知)的类型有:

基于AspectJ的AOP使用

其实就是指的Spring+AspectJ整合,不过Spring以及将AspectJ收录到自身的框架中了,并且底层织入依然是采取的动态织入方式。

切入点表达式

切入点表达式的格式:

表达式格式说明:

  • execution:必须要

  • 修饰符:可省略

  • 返回值类型:必须要,但是可以使用*通配符

  • 包名:

  • 类名

  • 方法名:

  • 参数

通知类型

通知类型(五种):前置通知,后置通知,最终通知,环绕通知,异常抛出通知。

前置通知:

后置通知:

最终通知:

环绕通知:

异常抛出通知:

使用注解实现

  1. 编写切面类(注意不是通知类,因为该类中可以指的切入点)

  2. 环绕通知注解
    @Around

  3. 定义通用切入点
    使用@PointCut注解再切面类中定义一个通用的切入点,其他通知可以引用该切入点

纯注解方式

代理模式

其实每个模式名称就表明了该模式的作用,戴爱玲模式就是多一个代理类出来替原对象进行一些操作。代理又分为动态代理和静态代理。

静态代理

比如租房子找中介

静态代理的重点:

  • 需要为源类手动编写一个代理类
  • 代理类和源类实现同一接口。
  • 代理对象持有源对象的引用。

静态代理的缺点:

  • 会产生大量的代理类。
代理模式的应用场景:

如果已有的方法再使用的时候需要对原有的方法进行改进,此时有俩种办法:

  1. 修改原有的方法来适应,这样违反了“对扩展开发,对修改关闭”的原则
  2. 就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

动态代理

动态代理再编译期间,不需要为源类去手动编写一个代理类

只会再运行期间,去为源对象产生一个代理对象。

JDK动代理和Cglib动态代理的区别

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91280 人正在系统学习中

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年8月3日
下一篇 2021年8月3日

相关推荐