spring提供了两个核心功能,一个是IoC(控制反转),另外一个便是Aop(面向切面编程),IoC有助于应用对象之间的解耦,AOP则可以实现横切关注点(如日志、安全、缓存和事务管理)与他们所影响的对象之间的解耦。

1.简介

AOP主要包含了通知、切点和连接点等术语,介绍如下

  • 通知(Advice)
    通知定义了切面是什么以及何时调用,何时调用包含以下几种

    Before 在方法被调用之前调用通知
    After 在方法完成之后调用通知,无论方法执行是否成功
    After-returning 在方法成功执行之后调用通知
    After-throwing 在方法抛出异常后调用通知
    Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

  • 切点(PointCut)
    通知定义了切面的什么何时,切点定义了何处,切点的定义会匹配通知所要织入的一个或多个连接点,我们通常使用明确的类的方法名称来指定这些切点,或是利用正则表达式定义匹配的类和方法名称来指定这些切点。
    切点的格式如下

    execution(* com.ganji.demo.service.user.UserService.GetDemoUser (..) )

  • 连接点(JoinPoint)
    连接点是在应用执行过程中能够插入切面的一个点,这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时,切面代码可以利用这些连接点插入到应用的正常流程中,并添加新的行为,如日志、安全、事务、缓存等。

现阶段的AOP框架
AOP框架除了Spring AOP之外,还包括AspectJJBoss AOP
上述框架的区别是Spring AOP只支持到方法连接点,另外两个还支持字段和构造器连接点。

2.用法

同依赖注入一样,AOP在spring中有两种配置方式,一是xml配置的方式,二是自动注解的模式。

  • 2.1 xml中声明切面

    • 2.1.1 AOP配置元素

    在xml中,我们使用如下AOP配置元素声明切面

       AOP配置元素 | 描述
    ------------ | -------------
    `<aop:advisor>` | 定义AOP通知器
    `<aop:after>` | 定义AOP后置通知(不管该方法是否执行成功)
    `<aop:after-returning>` | 在方法成功执行后调用通知
    `<aop:after-throwing>` | 在方法抛出异常后调用通知
    `<aop:around>` | 定义AOP环绕通知
    `<aop:aspect>` | 定义切面
    `<aop:aspect-autoproxy>` | 定义`@AspectJ`注解驱动的切面
    `<aop:before>` | 定义AOP前置通知
    `<aop:config>` | 顶层的AOP配置元素,大多数的<aop:*>包含在<aop:config>元素内
    `<aop:declare-parent>` | 为被通知的对象引入额外的接口,并透明的实现
    `<aop:pointcut>` | 定义切点
    • 2.1.2 定义切面

    我们在service层添加com.ganji.demo.service.aspect.XmlAopDemoUserLog类,里面实现了拦截方法,具体如下


    package com.ganji.demo.service.aspect; import org.aspectj.lang.ProceedingJoinPoint; /**
    * Created by admin on 2015/9/2.
    */
    public class XmlAopDemoUserLog {
    // 方法执行前通知
    public void beforeLog() {
    System.out.println("开始执行前置通知 日志记录");
    }
    // 方法执行完后通知
    public void afterLog() {
    System.out.println("开始执行后置通知 日志记录");
    }
    // 执行成功后通知
    public void afterReturningLog() {
    System.out.println("方法成功执行后通知 日志记录");
    }
    // 抛出异常后通知
    public void afterThrowingLog() {
    System.out.println("方法抛出异常后执行通知 日志记录");
    } // 环绕通知
    public Object aroundLog(ProceedingJoinPoint joinpoint) {
    Object result = null;
    try {
    System.out.println("环绕通知开始 日志记录");
    long start = System.currentTimeMillis(); //有返回参数 则需返回值
    result = joinpoint.proceed(); long end = System.currentTimeMillis();
    System.out.println("总共执行时长" + (end - start) + " 毫秒");
    System.out.println("环绕通知结束 日志记录");
    } catch (Throwable t) {
    System.out.println("出现错误");
    }
    return result;
    }
    }
    • 2.1.3 xml声明切面并调用

    我们在web层,web-inf/dispatcher-servlet.xml中定义切面,具体如下


    <!--定义切面 指定拦截方法时 做什么-->
    <bean id="xmlAopDemoUserLog" class="com.ganji.demo.service.aspect.XmlAopDemoUserLog"></bean>
    <aop:config>
    <aop:aspect ref="xmlAopDemoUserLog"> <!--指定切面-->
    <!--定义切点-->
    <aop:pointcut id="logpoint" expression="execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..))"></aop:pointcut>
    <!--定义连接点-->
    <aop:before pointcut-ref="logpoint" method="beforeLog"></aop:before>
    <aop:after pointcut-ref="logpoint" method="afterLog"></aop:after>
    <aop:after-returning pointcut-ref="logpoint" method="afterReturningLog"></aop:after-returning>
    <aop:after-throwing pointcut-ref="logpoint" method="afterThrowingLog"></aop:after-throwing>
    </aop:aspect>
    </aop:config>

    在controller下调用,调用具体如下

    DemoUserEntity demoUser=userService.GetDemoUser(1);

    这是运行起来 我们将看到打印出如下日志

    开始执行前置通知 日志记录
    开始执行后置通知 日志记录
    方法成功执行后通知 日志记录

    • 2.1.4 小结

    如果通过xml配置,我们还可以实现环绕通知,环绕通知的目的是把前置通知和后置通知的信息共享起来。同时还可以为通知传递方法的参数,在切面拦截中验证参数的有效性。

  • 2.2 自动注解AOP

    在上述2.1中我们通过xml配置的形式 实现了AOP编程,现在我们通过不配置xml,配置注解的形式实现AOP。

    • 2.2.1 配置自动代理

    使用配置注解,首先我们要将切面在spring上下文中声明成自动代理bean,我们需要在web层的web-inf/dispatcher-servlet.xml文件中配置如下一句话即可

    <aop:aspectj-autoproxy />

    当然我们需要在xml的根目录beans下引用aop的命名空间和xsi


    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    • 2.2.2 使用@Aspect注解

    声明一个切面,只需要在类名上添加@Aspect属性即可,具体的连接点,我们用@Pointcut@Before@After等标注。具体如下
    在声明前 我们需要依赖配置pom


    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.6.11</version>
    </dependency>
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.6.11</version>
    </dependency>

    声明切面类,包含了注解@Aspect以及何时(如@Before)执行通知

    package com.ganji.demo.service.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Service; /**
    * Created by admin on 2015/9/2.
    */
    @Aspect
    @Service
    public class XmlAopDemoUserLog { // 配置切点 及要传的参数
    @Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)")
    public void pointCut(int id)
    { } // 配置连接点 方法开始执行时通知
    @Before("pointCut(id)")
    public void beforeLog(int id) {
    System.out.println("开始执行前置通知 日志记录:"+id);
    }
    // 方法执行完后通知
    @After("pointCut(id)")
    public void afterLog(int id) {
    System.out.println("开始执行后置通知 日志记录:"+id);
    }
    // 执行成功后通知
    @AfterReturning("pointCut(id)")
    public void afterReturningLog(int id) {
    System.out.println("方法成功执行后通知 日志记录:"+id);
    }
    // 抛出异常后通知
    @AfterThrowing("pointCut(id)")
    public void afterThrowingLog(int id) {
    System.out.println("方法抛出异常后执行通知 日志记录"+id);
    } // 环绕通知
    @Around("pointCut(id)")
    public Object aroundLog(ProceedingJoinPoint joinpoint,int id) {
    Object result = null;
    try {
    System.out.println("环绕通知开始 日志记录"+id);
    long start = System.currentTimeMillis(); //有返回参数 则需返回值
    result = joinpoint.proceed(); long end = System.currentTimeMillis();
    System.out.println("总共执行时长" + (end - start) + " 毫秒");
    System.out.println("环绕通知结束 日志记录");
    } catch (Throwable t) {
    System.out.println("出现错误");
    }
    return result;
    }
    }
    • 2.2.3 总结

    按照上述两个步骤,使用注解实现Aop即可,这里依赖了IOC。

Spring AOP @Aspect的更多相关文章

  1. Spring AOP(aspect oriented programming) 转载

    1.面向切面的基本原理 软件系统可以看成是由一组关注点组成的,其中,直接的业务关注点,是直切关注点.而为直切关注点提供服务的,就是横切关注点. 01.什么是面向切面编程 横切关注点:影响应用多处的功能 ...

  2. Spring AOP Aspect的简单实现(基于XML)

    第一步:导包 第二步:实现类和切面类 Service("userService")public class IUserviceImpl implements IUserServic ...

  3. Spring AOP Aspect的简单实现(基于注解)

    第1步:声明使用注解 <!-- 配置扫描注解--> 扫描包的位置<context:component-scan base-package="com.zz"/> ...

  4. [Spring] AOP, Aspect实例解析

    最近要用到切面来统一处理日志记录,写了个小实例练了练手: 具体实现类: public interface PersonServer { public void save(String name); p ...

  5. 基于注解的Spring AOP的配置和使用

    摘要: 基于注解的Spring AOP的配置和使用 AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不 ...

  6. Spring AOP在函数接口调用性能分析及其日志处理方面的应用

    面向切面编程可以实现在不修改原来代码的情况下,增加我们所需的业务处理逻辑,比如:添加日志.本文AOP实例是基于Aspect Around注解实现的,我们需要在调用API函数的时候,统计函数调用的具体信 ...

  7. 基于注解的Spring AOP的配置和使用--转载

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  8. Spring AOP 注解和xml实现 --转载

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  9. Spring学习十四----------Spring AOP实例

    © 版权声明:本文为博主原创文章,转载请注明出处 实例 1.项目结构 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

随机推荐

  1. Vuejs自定义全局组件--loading

    不管是使用框架,还是不使用任何的框架,我们都不可避免的需要与“加载中……”打交道,刚刚学习了Vuejs自定义组件的写法,就现学现卖,介绍一下吧! 先看一下目录结构,一般情况下,每一个组件都新建一个新的 ...

  2. GNU C语言开发环境

    1. GNU C 编译器 2. GNU make 项目管理工具 3. 创建和使用函数库 4. GNU C 函数库(glibc) 1.GNU C 编译器 使用 c语言 编写的代码,运行前必须经过编译和链 ...

  3. android 实现一个简单纯文本的ListView

    思维线路: 1.创建一个ListViewActivity,LinearLayout布局里写了一个ListView布局 2.创建一个TextView布局给ArrayAdapter适配器使用 3.将Tex ...

  4. 【转】 .Net MVC4 上传大文件,并保存表单

    1前台:cshtml </pre><pre name="code" class="csharp">@model BLL.BLL.Prod ...

  5. JSP 静态文件路径配置

    在JSP中,往往需要引入一些静态文件. 例如这样引用. 往往因为目录结构的问题,不知道是用点还是 .../ ./ ../表示相对当前路径的上一级目录:./表示相对当前的路径: 这里有个快捷的办法. l ...

  6. Java-左移右移-jdk8

    移位有三种 << 左移,左边补0 >> 右移,正数左边补0,负数补1 >>> 右移, 正数,负数统一左边补0 来看几个奇葩的代码 public static ...

  7. jenkins部署配置

    https://www.cnblogs.com/rslai/p/8135460.html 修改jenkins的默认端口号: https://blog.csdn.net/qq_32440951/arti ...

  8. 使用STM32的USART的同步模式Synchronous调戏SPI【usart模拟spi理论】

    [原创出品§转载请注明出处] 出处:http://www.cnblogs.com/libra13179/p/7064321.html 什么东西?? 我们先来看我们平常看到SPI的时序图(呵呵,要是忘记 ...

  9. 利用STM32CubeMX来生成USB_HID_Mouse工程【添加ADC】(1)

    现在原来的基础上添加ADC的功能. 现在(利用STM32CubeMX来生成USB_HID_Mouse工程)基础上新增硬件 JoyStick Shield 游戏摇杆扩展板 与STM32F103C8的连接 ...

  10. ABAP-1-会计凭证批量数据导入本地ACCESS

    公司会计凭证导入ACCESS数据库,需要发送给审计,原先的方案是采用DEPHI开发的功能(调用函数获取会计凭证信息,然后INSERT到ACCESS数据表),运行速度非常慢,业务方要求对该功能进行优化, ...