Java Spring AOP用法

Spring AOP

Java web 环境搭建

Java web 项目搭建

Java Spring IOC用法

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。

Java Spring AOP用法的更多相关文章

  1. 从零开始学 Java - Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就 ...

  2. 从零开始学 Java - Spring AOP 实现主从读写分离

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  3. Java Spring IOC用法

    Java Spring IOC用法 Spring IoC 在前两篇文章中,我们讲了java web环境搭建 和 java web项目搭建,现在看下spring ioc在java中的运用,开发工具为In ...

  4. 【转】Java Spring AOP详解

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  5. 从零开始学 Java - Spring AOP 拦截器的基本实现

    一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...

  6. Java - Spring AOP 拦截器的基本实现

    一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...

  7. Spring AOP 用法浅谈(Day_18)

    当你这一天没有在进步,那你就是在退步! [简述] Aspect Oriented Programming :面向切面编程 所谓面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情 ...

  8. 最全的Spring AOP

    1.什么是AOP? AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, ...

  9. Java缓存框架使用EhCache结合Spring AOP

    一.Ehcache简介     EhCache是一个纯Java的进程内缓存框架,具有如下特点:     1. 快速简单,非常容易和应用集成.     2.支持多种缓存策略 .     3. 缓存数据有 ...

随机推荐

  1. Oracle 表空间

    表空间 编辑 本词条缺少信息栏,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 表空间是数据库的逻辑划分,一个表空间只能属于一个数据库.所有的数据库对象都存放在指定的表空间中.但主要存放的是表 ...

  2. 让Asp.net mvc WebAPI 支持OData协议进行分页查询操作

    这是我在用Asp.net mvc WebAPI 支持 OData协议 做分页查询服务时的 个人拙笔. 代码已经开发到oschina上.有兴趣的朋友可以看看,欢迎大家指出不足之处. 看过了园子里的几篇关 ...

  3. string&&char 小技巧

    关于string =,assign()   //赋以新值 swap()   //交换两个字符串的内容 +=,append(),push_back() //在尾部添加字符 insert() //插入字符 ...

  4. H5学习系列之Geolocation API

    获取位置信息途径: 1.IP地址地理定位数据 2.GPS地理定位数据 3.WI-FI地理定位数据 4.手机地理定位数据 无废话直接上重点:navigator.geolocation对象就是获取地理位置 ...

  5. discuz二次开发,分析和实现 之 向dz数据库插入自己的帖子吧

    发个博客太麻烦了,难怪写博客的越来越少,吐一下,cnblogs的编辑器模板太丑! 最近开发社区 需要采集一些数据,使得模板输出有图文效果.就写了个简单的采集脚本,爬取目标站的内容,(用php 下载图片 ...

  6. .net加密解密

    .net加密概述 .net加密编程模型 .net加密解密类

  7. C# 网络与Cmd命令

    网络命令行: 1 - ping 2 - ipconfig 本机网络配置情况 3 - net 4 - arp  网络网卡物理/ip地址对应用 5 - tracert 列举数据报到达目标地所经过的网关 6 ...

  8. [WPF]建立自适应窗口大小布局的WinForm窗口

    编写WinForm程序时,都会碰到一个问题.就是WinForm窗口在不同分辨率下的大小问题.举例说明,你编写的WinForm窗口在1024×768下是合适.匀称的.不过,如果用户的计算机的分辨率为14 ...

  9. Red hat 6.4下面的qt安装

    运行环境:Red hat 6.4 去官网下载qt5.2并且安装 当启动的时候会出现如下错误 核心载入失败: /opt/Qt5.2.0/Tools/QtCreator/lib/qtcreator/plu ...

  10. javascript鸭式辩型法实现接口

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...