Spring基础知识之AOP的理解与应用

AOP是什么?

  面向切面编程,传统的OOP开发中的代码逻辑是自上而下的,而这些过程会产生一些横切性的问题,这些横切性的问题与我们的业务逻辑关系不大,这些横切性的问题不会影响到主业务逻辑的实现,但是会散落到代码的各个部分,难以维护。AOP就是处理一些横切性的问题,AOP的编程思想就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的,使代码的重用性的开发效率更高。

APO的应用场景?

  1.   日志记录
  2.   权限验证
  3.   效率检查
  4.   事务处理
  5.   exception

SpringAOP 和 AspectJ的关系?

  AOP是一种编程理念,SpringAOP和AspectJ都是AOP的实现,SpringAOP有自己的语法,但是语法过于复杂,所以SpringAOP借助了AspectJ的注解,但是底层还是自己的。

SpringAOP提供的两种编程风格:

   1.使用@Aspect注解

   2.使用xml配置,aop:config命名空间

SpringAOP支持AspectJ的步骤:

  1.启用@AspectJ注解:使用Java@Configuration启用@AspectJ支持,添加@EnableAspectJAutoProxy注解

 1 /**
 2  * 使用注解实现aop代理
 3  * @author Administrator
 4  *
 5  */
 6 @Configuration
 7 @EnableAspectJAutoProxy
 8 @ComponentScan
 9 public class AOPAnnotation {
10 
11 }

  2.声明一个@AspectJ注释类,并且定义成一个bean交给spring容器管理。

 1 /**
 2  * 1.创建aop的切面类
 3  * @author Administrator
 4  *
 5  */
 6 @Component//首先加入spring容器中
 7 @Aspect//使用aspectj注解
 8 public class AspectjUtil {
 9 
10     
11 }

  3.声明一个pointCut,切入点表达式有@Pointcut注释表示,切入点声明由两部分组成,一个签名包含名称和任何参数,以及一个切入点表达式,该切入点表达式确定我们对哪个方法的执行感兴趣。

  声明切入点的几种方式(后面有详细讲解):

    1.execution,匹配方法执行连接点

    2.within,将匹配限制为特定类型中的连接点

    3.args,参数

    4.target,目标队形

    5.this,代理对象

 1 /**
 2  * 1.创建aop的切面类
 3  * @author Administrator
 4  *
 5  */
 6 @Component//首先加入spring容器中
 7 @Aspect//使用aspectj注解
 8 public class AspectjUtil {
 9 
10     /**
11      * 2.声明一个切点
12      * @Description: TODO
13      * @returnType: void
14      */
15     @Pointcut("execution(* org.wk.spring.dao.*.*(..))")//切入点表达式
16     public void pointCut(){//切入点签名
17         System.out.println("pointCut方法");
18     }
19 }

  4.声明一个Advice通知,advice通知和pointcut切入点表达式相关联,并在切入点匹配的方法执行@Before之前,@After之后或前后运行。

 1 /**
 2  * 1.创建aop的切面类
 3  * @author Administrator
 4  *
 5  */
 6 @Component//首先加入spring容器中
 7 @Aspect//使用aspectj注解
 8 public class AspectjUtil {
 9 
10     /**
11      * 2.声明一个切点
12      * @Description: TODO
13      * @returnType: void
14      */
15     @Pointcut("execution(* org.wk.spring.dao.*.*(..))")//切入点表达式
16     public void pointCut(){//切入点签名
17         System.out.println("pointCut方法");
18     }
19     
20     /**
21      * 3.定义通知点
22      * @Description: TODO
23      * @returnType: void
24      * 声明before通知,在pointcut切入点之前运行
25      */
26     @Before("pointCut()")
27     public void before(){
28         //编写通知的逻辑
29         System.out.println("在pointCut方法之前");
30     }
31 }

各个连接点Pointcut的意义?

  1.execution,用于匹配方法执行join points连接点,表达式的最小粒度是方法,在aop中最多使用。

    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

    这里问号表示当前项可以有也可以没有,其中各项的语义如下

    modifiers-pattern:方法的可见性,如public,protected;
    ret-type-pattern:方法的返回值类型,如int,void等;
    declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
    name-pattern:方法名类型,如buisinessService();
    param-pattern:方法的参数类型,如java.lang.String;
    throws-pattern:方法抛出的异常类型,如java.lang.Exception;
    example:
    @Pointcut("execution(* com.chenss.dao.*.*(..))")//匹配com.chenss.dao包下的任意接口和类的任意方法
    @Pointcut("execution(public * com.chenss.dao.*.*(..))")//匹配com.chenss.dao包下的任意接口和类的public方法
    @Pointcut("execution(public * com.chenss.dao.*.*())")//匹配com.chenss.dao包下的任意接口和类的public 无方法参数的方法
    @Pointcut("execution(* com.chenss.dao.*.*(java.lang.String, ..))")//匹配com.chenss.dao包下的任意接口和类的第一个参数为String类型         的方法
    @Pointcut("execution(* com.chenss.dao.*.*(java.lang.String))")//匹配com.chenss.dao包下的任意接口和类的只有一个参数,且参数             为String类型的方法
    @Pointcut("execution(public * *(..))")//匹配任意的public方法
    @Pointcut("execution(* te*(..))")//匹配任意的以te开头的方法
    @Pointcut("execution(* com.chenss.dao.IndexDao.*(..))")//匹配com.chenss.dao.IndexDao接口中任意的方法
    @Pointcut("execution(* com.chenss.dao..*.*(..))")//匹配com.chenss.dao包及其子包中任意的方法

  由于Spring切面粒度最小是表达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的信息,并且在spring中,大部分使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用范围是最为广泛的。

  2.within,表达式的最小粒度为类。

    @Pointcut("within(com.chenss.dao.*)")//匹配com.chenss.dao包中的任意方法

    @Pointcut("within(com.chenss.dao..*)")//匹配com.chenss.dao包及其子包中的任意方法
  within与execution相比,粒度更大,仅能实现到包和接口,类级别,而execution可以精确到方法的返回值,参数个数,修饰符,参数类型等。

  3.args,表达式的作用是匹配指定参数类型和指定参数数量的方法,与包名和类名无关。

    @Pointcut("args(java.io.Serializable)")//匹配运行时传递的参数类型为指定类型的、且参数个数和顺序匹配
    @Pointcut("@args(com.chenss.anno.Chenss)")//接受一个参数,并且传递的参数的运行时类型具有@Classified
  args同execution不同的地方在于:
    args匹配的是运行时传递给方法的参数类型
    execution(* *(java.io.Serializable))匹配的是方法在声明时指定的方法参数类型。

   4.this,在使用JDK代理时,代理对象指向接口和代理类Proxy,使用cglib代理时,代理对象指向接口和子类(不使用Proxy)

  5.target,代理对象指向接口和子类

    此处需要注意的是,如果配置设置proxyTargetClass=false,或默认为false,则是用JDK代理,否则使用的是CGLIB代理。

    JDK代理的实现方式是基于接口实现,代理类继承Proxy,实现接口

    CGLIB继承被代理的类来实现

    所以使用target会保证目标不变,关联对象不会受到这个设置的影响。

    但是使用this时,会根据该选项的设置,判断时候能找到对象。

    @Pointcut("target(com.chenss.dao.IndexDaoImpl)")//目标对象,也就是被代理的对象。限制目标对象为com.chenss.dao.IndexDaoImpl类

    @Pointcut("this(com.chenss.dao.IndexDaoImpl)")//当前对象,也就是代理对象,代理对象时通过代理目标对象的方式获取新的对象,与原值并非一个

    @Pointcut("@target(com.chenss.anno.Chenss)")//具有@Chenss的目标对象中的任意方法

    @Pointcut("@within(com.chenss.anno.Chenss)")//等同于@target

  

猜你喜欢

转载自www.cnblogs.com/wk-missQ1/p/12416688.html
今日推荐