基本概念

  • 通知

   就是你想要的功能,也就是我们常说的安全、事物、日志等。先定义好这些,然后再想用的地方用一下。包含Aspect的一段处理代码

    注意:其实这些功能(通知)并不是我们业务逻辑所必须的,只是为了安全,输出信息,或者其他的原因,总之是为了方便我们对项目维护而增加的操作,一般我们会把这些功能封装成相关的方法,但是我们又不想这些功能直接入侵我们的正常业务代码,因为这样会增加关注度并且污染我们的业务逻辑,所以我们就用切面的思想来很好解决这个问题

  • 连接点

    就是spring允许你加 通知(Advice)的地方,那可就真多了,基本每个方法的前、后(两者都有也行),或抛出异常时都可以是连接点,spring一般只支持方法连接点,除非引入其他的aop框架才可以实现更细粒度的连接点。其他如AspectJ还可以让你在构造器或属性注入时都行,不过那不是咱们关注的,只要记住,和方法有关的前前后后都是连接点

  • 切入点

    在上面说的连接点的基础上,来定义切入点。例如:你的一个类里,有15个方法,那就有至少十几个连接点了对吧,但是你并不想在所有方法附近都使用通知(使用叫织入,下面再说),你只是想让其中几个,在调用这几个方法之前、之后或者抛出异常时干点什么,那么就用切入点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法

    注意:切入点定义的一般是你的业务中的某些方法(也有可能是某些特殊地方,在“特例”下有个例子切点切的就是方法,而是自定义的注解),就是供切面实际切入的地方,也就是需要执行通知的地方

  • 切面

     用来切插业务方法的类。

    切面是通知和切入点的结合。现在发现了吧,没连接点什么事,链接点就是为了让你好理解切点搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的befor,after,around等就能知道),二切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义

  • 目标

    引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面,而自己专注于业务本身的逻辑。

  • 代理

    怎么实现整套AOP机制的,都是通过代理,这个一会儿给细说

  • 织入(weaving) 

    把切面应用到目标对象来创建新的代理对象的过程。有三种方式,spring采用的是运行时,为什么是运行时,在上一文《Spring AOP开发漫谈之初探AOP及AspectJ的用法》中第二个标提到

  • 目标对象 

    项目原始的Java组件。

  • AOP代理  

    由AOP框架生成java对象。

  • AOP代理方法 

    代理方法= advice + 目标对象的方法。

xml方式配置详解

  • aop所需jar包

       <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.9</version>
    </dependency>

  • 在使用xml方式的Aop时,首先要保证xml头部引入了aop包和spring的基础包,如下:

      <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:tx="http://www.springframework.org/schema/tx"
        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.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

  • 在spring-context.xml(也就是spring的主配置文件)中加入<aop:aspectj-autoproxy/>
  • aop具体代码

    <!-- 定义普通的Bean实例 -->

    <bean id="adviceTest" class="com.abc.advice.AdviceTest" />
    <!-Aop配置->
    <aop:config>
        <!-- 将容器中的adviceTest转换成切面Bean --> 
         <!-- 注意这里可以使用order属性为Aspect指定优先级 -->
        <aop:aspect id="firstAspect" ref="adviceTest" order="2">
          <!-切点第一种写法开始->
              <!-- @Before切点 -->
          <!-method属性对应的方法一定是切面中的方法->
              <aop:before pointcut="execution(* com.abc.service.*.*(..))" 
                      method="permissionCheck"  arg-names="name,age"/>
              <!-- @After切点 -->
              <aop:after pointcut="execution(* com.abc.service.*.*(..))" 
                      method="releaseResource"/>
              <!-- @AfterReturning切点 -->
              <aop:after-returning pointcut="execution(* com.abc.service.*.*(..))" 
                      method="log" returning="discussion" arg-names="discussion"/>
          注意:如果有returning属性,那么arg-names属性必须有,两者的属性值可以任意取名,但是必须一致,否者就会报错
              <!-- @AfterThrowing切点 -->
              <aop:after-throwing pointcut="execution(* com.abc.service.*.*(..))" 
                      method="handleException"/>
              <!-- @Around切点(多个切点提示符使用and、or或者not连接) -->
              <aop:around pointcut="execution(* com.abc.service.*.*(..)) and args(name,time,..)" 
                      method="process"/>
          <!-切点第一种写法结束->
 
             

          <!-切入点第二种写法开始->

          <!-单参数传参->

          <aop:pointcut      id="thinking"   expression="execution(* com.bird.springidol.Thinker.thinkOfSomething(String)) and args(thoughts)"/>

          <aop:before method="interceptThoughts" pointcut-ref="thinking" arg-names="thoughts"/>
          注意:这个配置的意思就是,拦截这个Thinker接口的实现方法,其中的参数命名为thoughts,
          下面的before方法里面的interceptThoughts方法接受一个参数,这个参数映射到thoughts这个地方,然后暗中的拦截方法就能接受到参数了
 
          <!-对象传参->

          <aop:pointcut id="log4add" expression="execution(* com.tfedu.discuss.web.TeacherDiscussionController.delete(com.tfedu.discuss.abutment.TestAddLog)) and            args(testAddLog)" />
          <aop:after method="addLog" pointcut-ref="log4add" arg-names="testAddLog"/>

          <!-切入点第二种写法结束->

          <!-切点为注解时,也就是将切点切到注解上 开始->

             <!-切点为注解时,也就是将切点切到注解上 结束-> 
          </aop:aspect>
    </aop:config>
    • pointcut-ref:当pointcut单独写时,在通知标签里,要是用pointcut-ref属性来指向响应的切点Id
    • method:一般对应的是切面中的通知方法
    • arg-names:定义的是通知方法中的参数。一般通知方法中需要使用切点方法的参数时,这个属性最好加上(当然有时不写也可以传参),并且和expression表达式中的args()的小括号中的名称保持一直
    • order:

      Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候,会遇到跟spring的事务aop执行的先后顺序问题,比如说动态切换数据源的问题,如果事务在前,数据源切换在后,会导致数据源切换失效,所以就用到了Order(排序)这个关键字.我们可以通过在@AspectJ的方法中实现org.springframework.core.Ordered 这个接口来定义order的顺序,order 的值越小,说明越先被执行

特例(某注解为切点时)

一般我们认为切点的位置都是某个业务方法之前,之后或者前后都有,但是有些情况下我们也可以将切点切到某个方法的注解上,在解决某些问题时很方便,下面举例说明此种用法:

配置文件中内容

    <bean id="abutmentAspect" class="com.tfedu.discuss.abutment.aop.LogAspect"></bean>
    <aop:config>
      <aop:aspect id="" ref="abutmentAspect">
        <aop:pointcut id="addLog" expression="@annotation(com.tfedu.discuss.annotation.BehaviorLog)" />
        <aop:after method="behaviorLog4Review" pointcut-ref="addLog"/>
      </aop:aspect>
    </aop:config>

注解类

     @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
    @Documented
    public @interface BehaviorLog {

      OperTypeEnum value();//这里面定义的方法要在注解上用到,这里的方法名就是注解上的等号左边的值

      String fiterName();

    }

注意:里面的方法可以根据具体需要来定义

注解的使用

  在业务方法上加上:@BehaviorLog(value = OperTypeEnum.REVIEW, fiterName = "historyDraftId")

通知方法代码

public void behaviorLog4Review(JoinPoint joinPoint) {
      Signature signature = joinPoint.getSignature();
      MethodSignature methodSignature = (MethodSignature) signature;
      Method method = methodSignature.getMethod();
      String fiterName = method.getAnnotation(BehaviorLog.class).fiterName();//这里获取的是注解中定义的各种方法的值,例如这里获取的注解上的fiterName等号后面的的值       Object[] args = joinPoint.getArgs();//这里获取的是方法里的参数不是注解上的值,这个切记
      Long historyDraftId = getParam4Common(args, fiterName);
      HistoryDraftEntity historyDraftEntity = historyDraftBaseService.get(historyDraftId);
      if (Util.isEmpty(historyDraftEntity)) {
        ExceptionUtil.bEx("批阅中添加行为日志记录是,历史稿对象不能为空", historyDraftEntity);
      }
      addLog(historyDraftId, LogTypeEnum.WRITING.key(), historyDraftEntity.getTitle(), fetchUser.getCurrentUserId(),
      OperTypeEnum.REVIEW.key());
    }            private Long getParam4Common(Object[] args, String fiterName) {
        Optional<Object> obj = Arrays.stream(args).findFirst();
        if (!obj.isPresent()) {
          return PARAM_ID;
        }
        return ConvertUtil.obj2long(BeanUtil.get((obj.get()), fiterName));
      }

Aop的基本介绍的更多相关文章

  1. Spring入门篇——第6章 Spring AOP的API介绍

    第6章 Spring AOP的API介绍 主要介绍Spring AOP中常用的API. 6-1 Spring AOP API的Pointcut.advice概念及应用 映射方法是sa开头的所有方法 如 ...

  2. AOP的成员介绍

    AOP(Aspect Oriented Programming)面向切面编程,AOP的作用不过多介绍,本文是主要是介绍AOP的成员,是我在复习的时候记录的一些笔记,方便以后查阅方便一些. JointP ...

  3. spring aop做什么介绍

    1.AOP(Aspect Orient Programming),称为面向切面编程,它作为面向对象(OOP)的一种补充,用于处理系统中分布于各个模板的横切关注点,比如事务管理.日志.缓存等.AOP实现 ...

  4. spring AOP(切面) 表达式介绍

    在 spring AOP(切面) 例子基础上对表达式进行介绍 1.添加接口删除方法 2.接口实现类 UserDaoServer 添加实现接口删除方法 3.测试类调用delUser方法 4. 输出结果截 ...

  5. [刘阳Java]_Spring AOP注解详细介绍_第8讲

    这节内容非常关键,我们会比较详细地介绍Spring AOP注解的使用 1. 要使用Spring AOP注解,必须满足如下的事项 导入Aspectj的jar.Spring3.0-AOP.jar.aopa ...

  6. Spring基础只是—AOP的概念介绍

    Spring容器包含两个重要的特性:面向切面编程(AOP)和控制反转(IOC).面向切面编程是面向对象(OOP)的一种补充,在面向对象编程的过程中编程针对的目标是一个个对象,而面向切面编程中编程针对的 ...

  7. Spring Aop重要概念介绍及应用实例结合分析

    转自:http://bbs.csdn.net/topics/390811099 此前对于AOP的使用仅限于声明式事务,除此之外在实际开发中也没有遇到过与之相关的问题.最近项目中遇到了以下几点需求,仔细 ...

  8. spring---aop(7)---Spring AOP中expose-proxy介绍

    写在前面 expose-proxy.为是否暴露当前代理对象为ThreadLocal模式. SpringAOP对于最外层的函数只拦截public方法,不拦截protected和private方法(后续讲 ...

  9. spring---aop(6)---Spring AOP中ProxyFactoryBean介绍

    写在前面 这篇文章里面就要说说Spring自己的AOP,搞清楚哪种方式是Spring自己实现的AOP,哪种方式是Spring引入aspectj的AOP. 简单例子 Spring自己的AOP实现在于Pr ...

随机推荐

  1. left join、right join、inner join的区别

    left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录inner join(等值连接) 只 ...

  2. mac通过路径找到对应的文件夹

    在finder中 command + shift + G 跳出窗口中输入指定的路径,即可到达.

  3. 命令查看linux主机配置

    查看cpu: # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数 cat /proc/cp ...

  4. ( 转 )超级惊艳 10款HTML5动画特效推荐

    今天我们要来推荐10款超级惊艳的HTML5动画特效,有一些是基于CSS3和jQuery的,比较实用,特别是前几个HTML5动画,简直酷毙了,现在将它们分享给大家,也许你能用到这些HTML5动画和jQu ...

  5. Go指南练习_Stringer

    源地址 https://tour.go-zh.org/methods/18 一.题目描述 通过让 IPAddr 类型实现 fmt.Stringer 来打印点号分隔的地址. 例如,IPAddr{1, 2 ...

  6. circRNA 中的ALU 重复元件

    circRNA 最初研究的很少,只有很小一部分基因有检测到circRNA, 当时都认为是剪切错误形成的,对于其功能也没人去研究:学者对人类的成纤维细胞进行转录组测序,构建去核糖体文库, 同时采用了RN ...

  7. 二、主流区块链技术特点及Hyperledger Fabric V0.6版本特点

    一.主流区块链技术特点 二.HyperLedger子项目 三.Hyperledger fabric架构 V0.6逻辑架构: V0.6区块链网络 对应的0.6版本的运行时架构: 0.6版本的架构特点是: ...

  8. linux memcached开机启动

    方法一: 在/etc/rc.d/rc.local 加入以下代码 /usr/local/memcached/bin/memcached -u root -d -m -l -P /tmp/memcache ...

  9. HTTP Status 500 - Could not open Hibernate Session for transaction;

    错误原因: mysql数据库没有连接上 我们来启动mysql 方法1: 管理员身份运行 cmd 输入:  net start mysql 方法2: Windows + R 运行 services.ms ...

  10. SQL Server -- 随笔

    -- 判断是否存在 LimeNextMonthBirthday 表 ) PRINT '存在' ELSE PRINT'不存在' -- 如果存在 则删除 没有 则打印 不存在 ) DROP TABLE L ...