Spring 通过来AOP 实现前置,环绕,异常通知,注解(转)

本节主要内容:     1. Spring AOP前置通知案例     2. Spring AOP环绕通知案例     3. Spring AOP异常通知案例     4. Spring AOP注解使用案例

 

AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续

 

关于Spring AOP的一些术语

  • 切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现
  • 连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行
  • 通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括"around"、"before”和"after"等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链
  • 切入点(Pointcut):定义出一个或一组方法,当执行这些方法时可产生通知,Spring缺省使用AspectJ切入点语法。

 

通知类型

  • 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)
  • 返回后通知(@AfterReturning):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回
  • 抛出异常后通知(@AfterThrowing):方法抛出异常退出时执行的通知
  • 后通知(@After):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)
  • 环绕通知(@Around):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为,它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行

 

Spring 实现AOP是依赖JDK动态代理和CGLIB代理实现的。 以下是JDK动态代理和CGLIB代理简单介绍     JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。     CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。   

在Spring中,有接口时将采用JDK的方式实现proxy代理对象,当没有接口时,将采用cglib中的方式实现prixy代理对象。

 

1 Spring AOP前置通知案例

1.1 问题

使用Spring AOP前置通知,在访问Controller中每个方法前,记录用户的操作日志。

1.2 方案

Spring AOP使用步骤:

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建Controller,创建新项目SpringAOP。

导入Spring 环境的jar包 :

      如果没有jar包,那么可以上去上面下一个。下载地址:http://yunpan.cn/cdXTcJtZfJqQk  访问密码 6c96

创建员工业务控制器EmpController,并实现员工查询,代码如下:

 

package com.souvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/emp")
public class EmpController {
    /**
     * 查询员工
     */
    @RequestMapping("/findEmp.do")
    public String find() {
        // 模拟查询员工数据
        System.out.println("查询员工数据,发送至列表页面.");
        return "emp/emp_list.jsp";
    }
}

 

步骤二:创建方面组件

创建方面组件OperateLogger,并在该类中创建记录用户操作日志的方法,代码如下:

package com.souvc.aspect;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * 用于记录日志的方面组件,演示Spring AOP的各种通知类型。
 */
public class OperateLogger {
    /**
     * 前置通知、后置通知、最终通知使用的方法
     */
    public void log1() {
        // 记录日志
        System.out.println("-->记录用户操作信息");
    }
}

 

步骤三:声明方面组件

在applicationContext.xml中,声明该方面组件,关键代码如下:

     

     <!-- 声明方面组件 -->  

    <bean id="operateLogger" class="com.souvc.aspect.OperateLogger"/>

 

 

步骤四:将方面组件作用到目标组件上

在applicationContext.xml中,将声明的方面组件作用到com.souvc.controller包下所有类的所有方法上,关键代码如下:

<!-- 声明方面组件 -->
    <bean id="operateLogger" class="com.souvc.aspect.OperateLogger"/>

    <!-- 配置AOP -->
    <aop:config>
        <aop:aspect ref="operateLogger">
            <aop:before method="log1"
                pointcut="within(com.souvc.controller..*)"/>
        </aop:aspect>
    </aop:config> 

 

步骤五:测试

创建Junit测试类TestEmpController,并增加测试查询员工的方法,代码如下:

package com.souvc.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.souvc.controller.EmpController;

public class TestEmpController {

    /**
     * 测试查询员工
     */
    @Test
    public void test1() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        EmpController ctl = ctx.getBean(EmpController.class);
        ctl.find();
    }
}

 

执行该测试方法,控制台输出效果:

-->记录用户操作信息
查询员工数据,发送至列表页面.

 

可见,在执行EmpController.find()方法之前,执行了方面组件的记录日志的方法,由于该方法采用AOP面向对象的思想实现的,因此不需要对Controller类做任何改动。

 

步骤六:扩展

后置通知、最终通知的用法与前置通知完全一致,只需要在配置AOP时将aop:before改为aop: after-returning和aop:after。请自己尝试将前置通知类型改为后置通知、最终通知,并执行测试方法,观察控制台的输出情况。

 

源码如下:http://yunpan.cn/cdXhDcB4dQMqv  访问密码 0f0b

 

 

2 Spring AOP环绕通知案例

2.1 问题

使用Spring AOP环绕通知,在访问Controller中每个方法前,记录用户的操作日志。

2.2 方案

Spring AOP使用步骤:

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建方面组件

复用方面组件OperateLogger,在该类中创建新的记录日志的方法log2,代码如下:

 

package com.souvc.aspect;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * 用于记录日志的方面组件,演示Spring AOP的各种通知类型。
 */
public class OperateLogger {
    /**
     * 前置通知、后置通知、最终通知使用的方法
     */
    public void log1() {
        // 记录日志
        System.out.println("-->记录用户操作信息");
    }

    /**
     * 环绕通知使用的方法
     */
    public Object log2(ProceedingJoinPoint p) throws Throwable {
        // 目标组件的类名
        String className = p.getTarget().getClass().getName();
        // 调用的方法名
        String method = p.getSignature().getName();
        // 当前系统时间
        String date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
                .format(new Date());
        // 拼日志信息
        String msg = "-->用户在" + date + ",执行了" + className + "." + method + "()";
        // 记录日志
        System.out.println(msg);

        // 执行目标组件的方法
        Object obj = p.proceed();

        // 在调用目标组件业务方法后也可以做一些业务处理
        System.out.println("-->调用目标组件业务方法后...");

        return obj;
    }

}

 

步骤二:声明方面组件

由于复用的方面组件已经声明,因此该步骤可以省略。

 

步骤三:将方面组件作用到目标组件上

在applicationContext.xml中,声明方面组件的log2方法,关键代码如下:

 

<aop:aspect ref="operateLogger">
   <aop:around method="log2"
                pointcut="within(com.souvc.controller..*)"/>
 </aop:aspect>

 

步骤四:测试

执行测试方法TestEmpController.test1(),控制台输出效果如下图:

 

-->用户在2015-08-17 05:59:13,执行了com.souvc.controller.EmpController.find()
查询员工数据,发送至列表页面.
-->调用目标组件业务方法后...

 

项目源码如下: http://yunpan.cn/cdXaI6kmcvVp3  访问密码 f4cd
http://www.cnblogs.com/liuhongfeng/p/4736947.html

时间: 2024-08-15 08:14:40

Spring 通过来AOP 实现前置,环绕,异常通知,注解(转)的相关文章

举例讲解Java的Spring框架中AOP程序设计方式的使用_java

1.什么是AOP AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续. 2.关于Spring AOP的一些术语: A.切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现 B.连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行 C.通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作.通

Spring中的AOP详解

本文摘自pandonix的博客.   此前对于AOP的使用仅限于声明式事务,除此之外在实际开发中也没有遇到过与之相关的问题.最近项目中遇到了以下几点需求,采用AOP来解决.一方面是为了以更加灵活的方式来解决问题,另一方面是借此机会深入学习Spring AOP相关的内容.本文是权当本人的自己AOP学习笔记,以下需求不用AOP肯定也能解决,至于是否牵强附会,仁者见仁智者见智. 面对需求: ①对部分函数的调用进行日志记录,用于观察特定问题在运行过程中的函数调用情况. ②监控部分重要函数,若抛出指定的异

【spring框架】AOP的Annotation实现(下)

了解下面的就了解了Spring的声明式异常管理的原理 1.织入点的语法: 下面给出一些通用切入点表达式的例子. 任意公共方法的执行: execution(public * *(..)) 任何一个名字以"set"开始的方法的执行: execution(* set*(..)) AccountService接口定义的任意方法的执行: execution(* com.xyz.service.AccountService.*(..)) 在service包中定义的任意方法的执行: executio

Spring中的AOP(七)——基于XML配置文件方式的AOP

    除了前面介绍的基于JDK1.5的注解方式来定义切面,切入点和增强处理外,Spring AOP也允许直接使用XML配置文件来管理它们.在JDK1.5之前,只能使用配置文件的方式来管理,在Spring2.X后提供了一个新的aop命名空间来定义切面.切入点和增强处理.     相比之下,使用XML配置文件方式有如下优点: 如果没有使用JDK1.5以上版本,只能使用XML配置文件的方式 对早期的Spring用于来说更加习惯,而且这种方式允许使用纯粹的POJO来支持AOP 采用XML配置方式时,我

Spring中的AOP(三)——基于Annotation的配置方式(一)

    AspectJ允许使用注解用于定义切面.切入点和增强处理,而Spring框架则可以识别并根据这些注解来生成AOP代理.Spring只是使用了和AspectJ 5一样的注解,但并没有使用AspectJ的编译器或者织入器,底层依然使用SpringAOP来实现,依然是在运行时动态生成AOP代理,因此不需要增加额外的编译,也不需要AspectJ的织入器支持.而AspectJ采用编译时增强,所以AspectJ需要使用自己的编译器来编译Java文件,还需要织入器.     为了启用Spring对@A

【Spring开发】—— AOP之方法级拦截

前言: 前面介绍了Spring的核心模块以及相关的依赖注入等概念.这篇讲解一下spring的另一个重点,AOP面向切面编程. 说道AOP不得不提到几个概念: 切面:也就是我们自己的一些业务方法. 通知:用于拦截时出发的操作. 切点:具体拦截的某个业务点. 这样说可能还是有点抽象,举个例子,下面是一个纸糊的多面体. 每个面都是一个业务方法,我们通过刺穿每一个面,都可以进入到内部,这个面就是一个切面. 刺穿的时候会发出声响,这就是一种通知. 而具体从哪个面刺入,这就是一个切入点的选择了. 这样说,应

Spring框架与AOP思想的研究与应用

摘要 本文对Spring框架中所包含的AOP思想以及事务管理进行了分析,并通过对一个业务对象实现加锁/解锁的操作,说明了动态代理模式的可行性与有效性. 关键词 AOP:横切关注点:控制反转:动态代理 引言 Aspect Oriented Programming(AOP)是近年来计算机技术中比较热门的话题之一.其发展历史从学术领域和研发机构的运用开始,目前流行的Spring应用程序框架将AOP思想融入了整个框架的设计开发与应用当中.使用Spring框架固然给我们的编程带来了好处与便利,但是同时存在

Spring中基于aop命名空间的AOP 一(一点准备工作和一个例子)

在某些时候,我们工程中使用的JDK 不一定就是1.5 以上,也就是说可能不支持Annotation 注解,这时自然也就不能使用@AspectJ 注解驱动的AOP 了,那么如果我们仍然想使用AspectJ 灵活的切入点表达式,那么该如何呢?Spring 为我们提供了基于xml schematic 的aop 命名空间,它的使用方式和@AspectJ 注解类似,不同的是配置信息从注解中转移到了Spring 配置文件中.在这里,我们将详细介绍如何使用Spring 提供的<aop:config/> 标签

Spring中的AOP(一)——AspectJ的基本使用

    AOP(Aspect Orient Programming),也就是面向切面编程,作为面向对象编程的一种补充,当前已经成为一种比较成熟的编程思想,其实AOP问世的时间并不长,甚至在国内的翻译还不太统一(另有人翻译为"面向方面编程").AOP和OOP(Object Orient Programming,面向对象编程)互为补充,OOP将程序分解成各个层次的对象,而AOP则将程序运行过程分解成各个切面.可以这样理解:OOP是从静态角度考虑程序结构,而AOP则从动态角度考虑程序运行过程