Spring(二)面向切面的Spring

  在直系学长曾经的指导下,参考了直系学长的博客(https://www.cnblogs.com/WellHold/p/6655769.html)学习Spring的另一个核心概念--面向切片编程,即AOP(Aspect Oriented Programming)。

  Java是一种经典的面向对象的编程语言(OOP,Object Oriented Programming)。而面向对象的编程语言有三大特性:封装、继承和多台。其中继承允许我们定义从上到下的关系,即子类可以继承父类的一些功能参数,也可以改写父类的一些功能参数。但是,要为分散的对象(即不是同一父类的对象,这里的父类不包括Object)引入一个公共的行为的时候,OOP就显得很乏力,它需要在每一个对象里头都添加这个共用的行为,这样的代码就会显得很重复,很繁杂,最典型的就是添加日志功能,这个日志功能和对象的核心功能毫无关系,但是腰围分散的对象添加日志功能,就必须打开每一个分散的封装好的对象,然后添加日志功能代码,将这种分散在各处与对象核心功能无关的代码,称为横切代码。为了解决这个问题,AOP就应用而生。

  AOP是将多个类的公共行为封装到一个可重用的模块(如我们上一段所说的日志功能)并将其命名为“Aspect”,即是说将那些和类的核心业务无关的,却为业务模块所公共调用的逻辑处理封装起来,便可以减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP弥补了OOP在横向关系上操作的不足。而实现AOP的技术的主要两种方式,其中一种就是我们《常用设计模式:代理模式》所提到的动态代理技术;还有一种方式就是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

  Spring的AOP的实现原理就是动态代理技术。

  一、代理模式

  通过之前学习过的设计模式可以知道,简而言之,代理模式就是:“代理人”尽力肩负着工作使命,当“代理人”不能解决某些问题时,就会“转交”给“本人”,这里的“转交”就是“委托”。

  那么,究竟什么是代理模式呢?所谓的代理模式,主要分为一下几个角色:1.代理方;2.目标方;3.客户方;为了让读者和将来的自己能够更好的理解这三个角色,举个例子,比如我们要在买一双鞋子,但是鞋店离我们很远,我们需要让一个朋友帮我们代购,那么在这个关系当中,我们就是作为客户方,朋友作为代理方,而鞋店则是目标方,我们需要做的是要讲我们要买的鞋子的需求告诉朋友听,然后朋友帮我们到店里去购买,购买之后还可以为我们的鞋子简单的包装之后再邮寄回我们。这就是代理的三方关系,从这个例子我们可以给出代理的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是代理类与委托类有同样的接口。

  在进一步理解这个代理类的作用,代理类除了能帮我们把消息递交给目标类之外,还可以为目标类预处理消息,过滤消息,事后处理消息等。在我们的例子中的体现就是朋友不仅可以帮我们买鞋子,还可以为鞋店提供一些购买请求的过滤,比如我们要买的鞋子如果鞋店没有,朋友会直接告诉我们没有这双鞋,而不需要到鞋店去再问一遍,并且在我们购买到鞋子之后,朋友还会负责之后的邮寄和鞋子的包装,这就是相当于代理类为目标类做的消息预处理,消息过滤,以及事后消息预处理。代理类的对象本身并不真正实现服务,而是通过调用目标类的对象的相关方法,来提供特定的服务,从我们的例子来看,朋友自身是不生产鞋子的,而是鞋店生产的鞋子,并且提供销售,是一个道理。真正的业务是由目标类来实现的,但是在实现目标类之前的一些公共服务,例如在项目开发中我们没有加入缓冲,日志这些功能,后期想加入,我们就可以使用代理来实现,而没有必要打开已经封装好的目标类。

  (1)静态代理模式

  静态代理模式,就是由程序员创建或特定工具自动生成的源代码,再对其编译。在程序运行前,代理的类文件就已经存在。

  (2)动态代理模式

  二、什么是面向切面编程

  在软件系统中,散布于应用中多处的功能被称为横切关注点。通常来讲,这些横切关注点从从概念上是与应用的业务逻辑相分离的(但是往往会直接嵌入到应用的业务逻辑之中)。把这些横切关注点与业务逻辑相分离正是面向切面编程所要解决的问题。

  简而言之,横切关注点可以被描述为影响应用多处的功能。

  

  例如,安全就是一个横切关注点,应用中的很多方法都会涉及到安全规则。上图展现了一个被划分为模块的典型应用。每个模块的核心功能都是为特定业务领域提供服务,但是这些模块都需要类似的辅助功能,例如安全和事务管理。

  如果要重用通用功能的话,最常见的面向对象技术是继承或委托。但是,如果在整个应用中都是用相同的基类,继承往往会导致一个脆弱的对象体系,而使用委托可能需要对委托对象进行复杂的调用。

  在使用面向切面编程时,仍然在一个地方定义通用功能,但是可以通过声明的方式定义这个功能要以何种方式在何处应用,而无需修改受影响的类。横切关注点可以被模块化为特殊的类,这些类被称为切面

  1.AOP各部分介绍

  

  (1)通知(Advice)

  切面的工作被称为通知。通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题。它应该在某个方法被调用之前?之后?之前和之后都调用?还是只在方法抛出异常时调用?

  Spring切面可以应用5中类型的通知:

  • 前置通知(Before):在目标方法被调用之前调用通知功能。
  • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么。
  • 返回通知(After-returning):在目标方法成功执行之后调用通知。
  • 异常通知(After-throwing):在目标方法抛出异常后调用通知。
  • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

  (2)连接点(Join point)

  应用可能有数以千计的时机应用通知,这些时机被称为连接点。连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

  (3)切点(Poincut)

  一个切面并不需要通知应用的所有连接点。切点有助于缩小切面所通知的连接点的范围。如果说通知定义了切面的“什么”和“何时”的话,那么切点就定义了“何处”。切点的定义会匹配通知所要织入的一个或多个连接点。通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。

  (4)切面(Aspect)

  切面是通知和切点的集合。通知和切点共同定义了切面的全部内容--它是什么,在何时和何处完成其功能。

  (5)引入(Introduction)

  引入允许我们向现有的类添加新方法或属性。新方法或属性被引入到现有的类中,可以在无需修改这些现有的类的情况下,让它们具有新的行为和状态。

  (6)织入(Weaving)

  织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。

  2.Spring对AOP的支持

  Spring提供了4中典型的AOP支持:

  • 基于代理的经典Spring AOP
  • 纯POJO切面
  • @AspectJ注解驱动的切面
  • 注入式AspectJ切面(适用于Spring各版本)

  二、通过切点来选择连接点

  三、使用注解创建切面

  四、在XML中声明切面  

  五、注入AspectJ切面

猜你喜欢

转载自www.cnblogs.com/BigJunOba/p/9100585.html