zoukankan      html  css  js  c++  java
  • Spring Aop基于注解的实现

    一.AspectOriented Programing,面向切面编程。

      AOP主要用于日志记录,性能统计,安全控制(权限控制),事务处理,异常处理等。将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
      Spring AOP织入增强(Advice)的方式有两种 如果连接点实现了接口采用jdk自带的动态代理的形式实现织入,如果连接点没有实现接口则采用动态字节码生成技术(CGLIB)实现织入。

    二.AOP常用术语:

    连接点(Joinpoint)

      增强程序执行的某个特定位置(要在哪个地方做增强操作)。Spring仅支持方法的连接点,既仅能在方法调用前,方法调用后,方法抛出异常时等这些程序执行点进行织入增强。

    切点(Pointcut)

      切点是一组连接点的集合。AOP通过“切点”定位特定的连接点。通过数据库查询的概念来理解切点和连接点的关系再适合不过了:连接点相当于数据库中的记录,而切点相当于查询条件。

    增强(Advice)

      增强是织入到目标类连接点上的一段程序代码。表示要在连接点上做的操作。

    切面(Aspect)

      切面由切点和增强(引介)组成(可以包含多个切点和多个增强),它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的链接点中。

    注解切面类例子:

    @Aspect
    public class LogAspect {
        @Pointcut("execution(* com.ctj.service.*.*(..))")
        public void pointcutName(){}
    
        @Before("pointcutName()")
        public void performance(){
            System.out.println("Spring AOP");
        }
    }

    三.常用注解:

    • @aspect 定义切面
    • @pointcut 定义切点
    • @before 标注Before Advice定义所在的方法
    • @afterreturning 标注After Returning Advice定义所在的方法
    • @afterthrowing 标注After Throwing Advice定义所在的方法
    • @after 标注 After(Finally) Advice定义所在的方法
    • @around 标注Around Advice定义所在的方法

    我们如何在定义切点(Pointcut)的时候指定一类Joinpoint呢?有两种方式 简单的方法名指定以及正则表达式两种方式。

    四.常用的@AspectJ形式Pointcut表达式的标志符:

    execution:

      Spring AOP仅支持方法执行类型的Joinpoint 所以execution将会是我们用的最多的标志符,用它来帮我们匹配拥有指定方法前面的Joinpoint。匹配规则如下:
    execution(modifiers-pattern? return-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern)

    • modifiers-pattern 修饰符 比如public private这种(可以指定可以不指定)
    • return-type-pattern 返回值类型(必须指定)
    • declaring-type-pattern 类型(可以是含包名的全路径类型 可以指定可以不指定)
    • name-pattern 方法名(必须指定)
    • param-pattern 参数类型(必须指定)

    方法的返回类型 方法名及参数部分的匹配模式是必须指定的 其他部分可以省略。
    我们还可以在表达式中使用两种通配符:*和..
      第一:*可以用于任何部分的匹配模式中,匹配相邻的多个字符,即一个Work 。如果放在了方法参数的位置标示参数是任何类型的。
    例如:execution(* *(String))
      第二:..通配符可以在两个位置使用 一个是declaring-type-pattern的位置,一个是在方法参数匹配模式的位置。
    如果是放在了方法类型的位置,可以指定多个层次的类型声明。例如:
    execution(void cn.spring.*.doSomething(*)) 指定到cn.spring下的所有类型。
    如果是放在了方法参数的匹配位置,则表示该方法可以有0到多个参数。例如:
    execution(void *.doSomething(..))

    within:

      within标志符只接受类型声明,它将匹配指定类型下所有的Joinpoint。
    例如:within(cn.spring.aop.target.*) 将会匹配 cn.spring.aop.target包下所有类型的方法级别的Joinpoint。

    @annotation

      使用@annotation标志符会检查系统中所有对象的所有方法级别Joinpoint,如果被检测的方法标注有@annotation标志符所指定的注解类型,那么当前方法所在的Joinpoint将被Pointcut表达式匹配。例如:@pointcut("@annotation(com.test.aop.log.ALog)") 匹配所有使用了ALog注解的方法。

    匹配表达式的维度有很多 上面只是一小部分常用的,并且这些维度是可以组合的 使用||或者$$等等
    例如:@around("within(com.test.finance..*) && @annotation(com.test.finance.platform.intf.base.db.ReadOnly)")

    在定义Advice的时候 我们匹配的维度可以直接写定义有@pointcut的方法名称 也可以直接使用定义@joinpoint的那一套东西来直接定义要在哪些地方织入(可以直接在Advice上指定匹配哪些方法)

    定义完切面之后我们要在spring中注册这个切面类,为了让spring能自动帮我们实现织入 我们还需要开启自动注入 在spring配置文件中:<aop:aspectj-autoproxy proxy-target-class="true"/> 这样spring就能在IOC容器找到所有要织入的方法 动态帮我们织入。

    五.一个完整的Spring AOP的小例子:

    业务类代码:

    package com.ctj.service;
    import org.springframework.stereotype.Service;
    
    @Service
    public class BusinessService {
    
        public void say(){
            System.out.println("Business Code");
        }
    }

    切面类定义:

    package com.ctj.aspect;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class LogAspect {
        @Pointcut("execution(* com.ctj.service.*.*(..))")
        public void pointcutName(){}
        @Before("pointcutName()")
        public void performance(){
            System.out.println("Spring AOP");
        }
    }

    spring-aop.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
        <aop:aspectj-autoproxy proxy-target-class="true"/>
        <bean id="logAspect" class="com.ctj.aspect.LogAspect">
        </bean>
    </beans>

    基于注解的Spring AOP需要JDK1.5版本以后才能使用,之前的版本需要使用基于Schema也就是配置文件的形式来实现,如果jdk版本高的话 建议还是使用注解的形式。

  • 相关阅读:
    [rabbitmq] python版本(六)远程过程调用
    [rabbitmq] python版本(五) 主题交换机
    物体运动学习笔记(一)
    基于TimeLine编辑角色动画(二)
    基于TimeLine编辑角色动画(一)
    SQlite常用操作封装
    unity三种资源加载方式Resources,AssetBundle,WebRequset的同步异步加载
    场景同步异步加载
    XML保存账号密码
    unity EditorWindow 绘制时间刻度
  • 原文地址:https://www.cnblogs.com/wuwuyong/p/13234765.html
Copyright © 2011-2022 走看看