Spring AOP基础知识学习——Annotation配置

来源:互联网 发布:ie11 找不到js 编辑:程序博客网 时间:2024/06/06 01:00

AOP(Aspect Orient Programming),也就是面向切面编程。
AOP从程序运行角度考虑程序的流程,提取业务处理过程的切面。AOP面向的是程序运行中各个步骤。
AOP代理其实是由AOP框架动态生成的一个对象,该对象可以作为目标对象使用。AOP代理包含了目标对象的全部方法,但AOP代理中的反复噶与目标对象的方法存在差异,AOP方法在特定切入点添加了增强处理,并回调了目标对象的方法。
AOP框架并不与特定的代码耦合,AOP框架能处理程序中执行中特定的关注点,而不与某个具体的类耦合。AOP有如下两个特征:

  • 各步骤之间的良好隔离性。
  • 源代码无关性。

下面是面向切面编程的一些术语:
这里写图片描述
Spring默认使用AspectJava切入点语法。

Spring目前仅支持将方法调用作为连接点,如果需要把对Fueld的访问和更新也作为增强处理的连接点,则可以考虑AspectJ。
AOP编程其实很简单,其中需要程序员参与的只有三部分:

  • 定义普通业务组件。
  • 定义切入点,一个切入点可能横切多个业务组件。
  • 定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作。
    Spring有如下两种选择来定义切入点和增强处理。
  • 基于Annotation的零配置方式:使用@Aspect、@Pointcut、等Annotation来标注切入点和增强处理。
  • 基于XML配置文件的管理方式:使用Spring配置文件来定义切入点和增强处理。

基于Annotation的零配置方式

为了启用Spring对@AspectJ切面配置的支持,并保证Spring容器中的目标Bean被一个或多个切面自动增强,必须在Spring配置文件中配置如下片段:

<?xml version="1.0" encoding="GBK"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop"    xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-4.2.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-4.2.xsd    http://www.springframework.org/schema/aop    http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">        <!-- 启动@AspectJ支持 -->    <aop:aspectj-autoproxy/></beans>

如果不打算使用Spring的XMLSchema配置方式,则应该在Soring配置文件中增加如下片段年启用@AspectJ支持。

<!--启动@AspectJ支持--><bean  class =”org.springframework.aop.aspectj.annotation.AnnotaionAwareAspectAutoProxyCreator”/>

上面的配置文件中的AnnotaionAwareAspectAutoProxyCreator是一个Bean后处理器,该Bean后处理器将会为容器中的Bean生成AOP代理。
1)定义切面Bean
当启动了@AspectJ支持后,只要我们在Spring容器中配置一个带@Aspect注释的Bean,Spring将会自动识别该Bean,并将该Bean作为切面处理。使用了@AspectJ的Bean不用担心会被后处理器增强处理。
2)定义Before增强处理
在一个切面类中使用@Before来标注一个方法时,该方法将作为Before增强处理。

@Aspectpublic class BeforeAdviceTest{    //匹配com.bh.service.impl包下所有类的、    //所有方法的执行作为切入点    @Before("execution(* com.bh.service.impl.*.*(..))")    public void authority(){        System.out.println("模拟执行权限检查");    }}

3)定义AfterReturning增强处理
AfterReturning增强处理将在目标方法正常完成后被织入。
使用@AfterReturning时可指定如下两个常用属性:
pointcut/value:这两个属性的作用是一样的,他们都用于指定该切入点对应的切入表达式。一样即可是一个已有的切入点,也可以直接定义切入点表达式。当指定了pointcut属性值后,value属性值将会被覆盖。
returning:指定一个返回值形参名,增强处理定义的方法可通过该形参名来访问目标方法的返回值。

import org.aspectj.lang.annotation.*;//定义一个切面@Aspectpublic class AfterReturningAdviceTest{    //匹配org.crazyit.app.service.impl包下所有类的、    //所有方法的执行作为切入点    @AfterReturning(returning="rvt"        , pointcut="execution(* com.bh.service.impl.*.*(..))")    public void log(Object rvt){        System.out.println("获取目标方法返回值:" + rvt);        System.out.println("模拟记录日志功能...");    }}

4)定义AfterThrowing增强处理
AfterThrowing增强处理主要用于处理程序中未处理的异常。
使用@AfterThrowing Annotation时可指定如下两个常用属性。

  • Pointcut/value:这两个属性的作用是一样的,他们都是用于指定该切入点对应的切入表达式。一样即可是一个已有的切入点,也可直接定义切入点表达式。党制定了pointcut属性值后,value属性值将会被覆盖。
  • Throwing:指定一个返回值形参名,增强处理定义的方法可通过该形参名来访问目标方法中所抛出的异常对象。
//定义一个切面@Aspectpublic class AfterThrowingAdviceTest{    //匹配org.crazyit.app.service.impl包下所有类的、    //所有方法的执行作为切入点    @AfterThrowing(throwing="ex"        , pointcut="execution(* com.bh.service.impl.*.*(..))")    public void doRecoveryActions(Throwable ex){        System.out.println("目标方法中抛出的异常:" + ex);        System.out.println("模拟抛出异常后的增强处理...");    }}

5)After增强处理
Spring提供了一个After增强处理,它与AfterReturning增强处理有点 相似,但也有区别:
AfterReturning增强处理只有在目标方法成功完成后才会被织入。
After增强处理不管目标方法如何结束(包括成功和遇到异常中止两种情况),他都会被织入。

//定义一个切面@Aspectpublic class AfterAdviceTest{    //匹配org.crazyit.app.service包下所有类的、    //所有方法的执行作为切入点    @After("execution(* com.bh.service.*.*(..))")    public void release(){        System.out.println("模拟方法结束后的释放资源...");    }}

6)Around增强处理
Around增强处理近似等于Before增强处理和AfterReturning增强处理的总和,Around增强处理既可以在执行目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作。
与Before增强处理、AfterReturning增强处理不同的是,Around增强处理甚至可以决定目标方法在什么时候执行,如何执行。甚至可以完全阻止目标方法的执行。
Around增强处理可以改变目标方法的参数值,也可以改变执行目标方法之后的返回值。
Around增强处理功能虽然强大,但是通常需要在线程安全的环境下使用。如果需要目标方法执行之前和之后共享某种状态数据,则可以考虑使用Around,尤其是需要使用增强处理阻止目标的执行或 需要改变目标方法返回值时,则只能使用Around增强处理。

package com.bh.advice;import org.aspectj.lang.annotation.*;import org.aspectj.lang.*;//定义一个切面@Aspectpublic class AroundAdviceTest{    //匹配org.crazyit.app.service.impl包下所有类的、    //所有方法的执行作为切入点    @Around("execution(* com.bh.service.impl.*.*(..))")    public Object processTx(ProceedingJoinPoint jp) throws java.lang.Throwable{        System.out.println("执行目标方法之前,模拟开始事务...");        //执行目标方法,并保存目标方法执行后的返回值        Object rvt = jp.proceed(new String[]{"被改变的参数"});        System.out.println("执行目标方法之后,模拟结束事务...");        return rvt + " 新增的内容";    }}

7)访问目标方法的参数
访问目标方法最简单的做法是定义增强处理方法时将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数代表了织入增强 处理的连接点。JoinPoint里包含了如下几个常用的方法。

  • Object[]getArgs();返回执行目标方法时的参数。
  • Singnature getSignature();返回被增强的方法的相关信息。
  • Object getTarget();返回被织入增强处理的目标对象。
  • Object getThis();返回AOP框架为目标对象生成的代理对象。

Before、Around、AfterReturning、After增强处理的优先级如下:

这里写图片描述
8)定义切入点
切入点实质就是为一个切入点表达式起一个名称,从而允许在多个增强处理中重用该名称。在SpringAOP中可以把切入点看成是所有能和切入表达式匹配的Bean方法。
切入点定义包含两个部分:

  • 一个切入点表达式。
  • 一个包含名字和任意参数的方法签名。

其中切入点表达式用于指定该切入点和哪些方法尽心匹配,包含名字和任意参数的方法签名将作为该切入点的名称。

package com.bh.advice;import org.aspectj.lang.annotation.*;@Aspectpublic class SystemArchitecture{    @Pointcut("execution(* com.bh.service.impl.Chin*.say*(..))")    public void myPointcut(){        System.out.println("my pointcut");    }}
package com.bh.advice;import org.aspectj.lang.annotation.*;@Aspectpublic class LogAspect{    //直接使用SystemArchitecture切面类的myPointcut切入点    //args(msg)保证该切入点只匹配只有一个字符串参数的方法    @AfterReturning(pointcut="SystemArchitecture.myPointcut()&&args(msg)" , returning="retVal")    public void writeLog(String msg, Object retVal){        System.out.println(msg);        System.out.println(retVal);        System.out.println("模拟记录日志....");    }}

9)切入点指示符
Spring AOP一共支持如下几种切入点指示符。

  • execution:用于匹配执行方法的连接点,这是SpringAOP中最主要的切入点指示符。该切入点的用法也相对复杂,execution表达式的格式如下:
    这里写图片描述
  • within:限定匹配特定类型的连接点,当使用Spring AOP的时候,只能匹配方法执行的连接点。
  • this:用于限定AOP代理必须是指定类型的实例,用于匹配该对象的所有连接点。当使用Spring AOP的时候,只能匹配方法执行的连接点。
  • target:用于限定目标对象必须是指定类型的实例,用于匹配该对象的所有连接点。当使用Spring
    AOP的时候,只能匹配方法执行的连接点。
  • args:用于连接点的参数类型进行限制,要求参数类型是指定类型的实例。当使用SpringAOP的时候,只能匹配方法执行的连接点。
  • bean:用于指定只匹配指定Bean实例内的连接点,实际上只能使用反复噶执行作为连接点。定义bean表达式时需要传入Bean的id或name,表示只匹配该Bean实例内的连接点,支持使用“*”通配符。

10)组合切入点表达式
Spring支持使用如下三个逻辑运算符来组合切入点表达式。
&&、||、!

0 0
原创粉丝点击