基本概念

  • 通知

   就是你想要的功能,也就是我们常说的安全、事物、日志等。先定义好这些,然后再想用的地方用一下。包含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. servlet中web.xml配置详解

    Web.xml常用元素 <web-app> 所有部署描述符文件的顶层(根)元素 <display-name></display-name>定义了WEB应用的名字 & ...

  2. 【GMT43智能液晶模块】例程六:WWDG看门狗实验——复位ARM

    实验原理: STM32内部包含窗口看门狗,通过看门狗可以监控程序运行,程序运行 错误时,未在规定时间喂狗,自动复位ARM.本实验通过UI界面中按钮按下 停止喂狗,制造程序运行错误,从而产生复位. 示例 ...

  3. 编译错误“The run destination My Mac is not valid for Running the scheme '***',解决办法

    [转载]   http://blog.csdn.net/duanyipeng/article/details/8007684   编译错误"The run destination My Ma ...

  4. django template if return false

    如果if的参数不存在于context中就会返回false 参考:http://stackoverflow.com/questions/11107028/django-template-if-true- ...

  5. Web - JSONP和同源策略漫谈

    0x00 前言 关于JSONP网上有很多文章了,我也是在拜读了别人的文章的基础上来写写自己的看法,这样可以加深自己印象,巩固一下学习效果.我们需要做的就是站在巨人的肩膀上眺望远方. 0x01 起 在W ...

  6. VS2012+openCV 2.4.8进行编译:VS2012 64位 使用OPENCV应用程序不能正常启动 (0xc000007b)怎么处理?

    [OpenCV入门教程之一] 安装OpenCV:OpenCV 2.4.8 +VS 开发环境配置 http://blog.csdn.net/poem_qianmo/article/details/198 ...

  7. java-信息安全(六)-基于RSA理解数字签名示例

    概述 java-信息安全(四)-数据签名.数字证书 java-信息安全(五)-非对称加密算法RSA RSA工具类 使用java-信息安全(五)-非对称加密算法RSA项目中RSACoder 数字签名理解 ...

  8. printf打印输出null问题的跟踪

    最近在工作中,遇到一处 printf输出有null的情况,在此记录一下,问题分析的过程. 测试代码很简单,本机为64位操作系统: #include <stdio.h> #include & ...

  9. [hive] hive 安装、配置

    一.hive安装 1.官网下载 1.2.2版本 http://apache.fayea.com/hive/hive-1.2.2/ 2. 解压,此处目录为 /opt/hadoop/hive-1.2.2 ...

  10. mysql按月查询

    SELECT DATE_FORMAT(GenerateTime, '%m') as month, SUM(GenerateCount) AS count FROM identitycodetask ' ...