AOP

在软件开发过程中,发布于应用程序多处的功能成为横切关注点,通常这些横切关注点是与应用程序分离的。

横切关注点被模块化为特殊的类,称为“切面”。通过声明的方式来决定切面在何处以何种方式被应用。

这样1,每个关注点都被集中在一个地方,而不是分散在多出代码。2,服务器比较简洁,只包含核心功能的代码,次要的关注点都被移动到切面上了。

AOP的术语

1, 切面:实现了横切关注点(事务、安全、日志等)的类,是通知和切点的集合

2, 通知:通知描述了切面要完成的工作,以及切面在合适执行这个工作

Spring的切面可以应用5种Advice
  Before :在方法调用之前调用通知
  After:之后,无论是否调用成功
  After-returning:返回之后
  After-throwing:抛出异常之后
  Around :在方法调用之前和之后通知

3, 连接点:应用程序中可以插入前面的位置,切面代码可以通过连接点插入到应用程序中

4, 切点:明确切面要织入的连接点的位置

5, 引入:引入允许向已知类中加入新的方法和属性

6, 织入:切面在指定的连接点织入到目标对象,在目标对象的声明周期中,有多个点可以织入,包括:编译期、类加载期、运行期

 Spring AOP是在运行期织入的。

Spring提供了4种类型的AOP支持:
1,基于代理的经典Spring AOP;
2,纯POJO切面;使用xml配置
3,@AspectJ注解驱动的切面;使用注解配置
4,注入式AspectJ切面(适用于Spring各版本) 。

Spring的通知是使用java编写,定义通知所应用的切点通常会使用注解或在Spring配置文件里采用XML来编写。

通过在代理类中包裹切面, Spring在运行期把切面织入到Spring管理的bean中

Spring只支持方法级别的连接点,不支持在字段上的连接点(比如说,某一个字段发生了变化做出响应的这种动作)和构造器连接点。

举例:

通过注解为类引入新的功能:
通过代理的方式,代理把委托的方法交给了另外一个类来实现,实现完了之后再交回给原来的类,实际上一个bean的实现被拆分到了多个类中。

在xml中声明切面

    <aop:config> 顶层的AOP配置元素。 大多数的<aop:*>元素必须包含在<aop:config>元素内
    <aop:advisor> 定义AOP通知器
    <aop:declare-parents> 以透明的方式为被通知的对象引入额外的接口
    <aop:pointcut> 定义一个切点
    <aop:aspect> 定义一个切面
    <aop:aspectj-autoproxy> 启用@AspectJ注解驱动的切面
    
    <aop:before> 定义一个AOP前置通知
    <aop:after> 定义AOP后置通知(不管被通知的方法是否执行成功)
    <aop:after-returning> 定义AOP返回通知
    <aop:after-throwing> 定义AOP异常通知
    <aop:around> 定义AOP环绕通知

XML可以吧一个POJO声明为一个切面,完成所有的Spring AOP的全部功能。

一个配置的例子如下

       <bean id="as1" class="aspect.as1"></bean>   定义切面的bean
       <aop:config> AOP的配置都放在config下,可以定义多个aspect,对应多个切面
           <aop:aspect ref="as1">   aspect定义一个切面,指向POJO的bean
               <aop:before
                       pointcut="execution(* Test.T1.doo(..)))"
                       method="Before"/>
               <aop:after
                       pointcut="execution(* Test.T1.doo(..)))"
                       method="After" />
               <aop:around
                       pointcut="execution(* Test.T1.doo(..)))"
                       method="Around" />
               <aop:after-throwing
                       pointcut="execution(* Test.T1.doo(..)))"
                       method="Throw"/>
           </aop:aspect>
       </aop:config>
       <aop:aspectj-autoproxy/>  启动自动代理

可以看到这里的PointCut都是一样的,可以定义出来一个PointCut进行简化,如下

      <aop:config>
           <aop:aspect ref="as1"> 在这里定义了PointCut,下面就可以直接使用了,也可以定义在config标签下面,这样所有的aspect都可以使用
               <aop:pointcut id="pc" expression="execution(* Test.T1.doo(..)))"/>
               <aop:before
                       pointcut-ref="pc"
                       method="Before"/>
               <aop:after
                       pointcut-ref="pc"
                       method="After" />
               <aop:around
                       pointcut-ref="pc"
                       method="Around" />
               <aop:after-throwing
                       pointcut-ref="pc"
                       method="Throw"/>
           </aop:aspect>
       </aop:config>
原文地址:https://www.cnblogs.com/Coder-Pig/p/7262687.html