本节主要内容: 1. Spring AOP前置通知案例 2. Spring AOP环绕通知案例 3. Spring AOP异常通知案例 4. Spring AOP注解使用案例
AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续
关于Spring AOP的一些术语
通知类型
Spring 实现AOP是依赖JDK动态代理和CGLIB代理实现的。 以下是JDK动态代理和CGLIB代理简单介绍 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。 CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。
在Spring中,有接口时将采用JDK的方式实现proxy代理对象,当没有接口时,将采用cglib中的方式实现prixy代理对象。
使用Spring AOP前置通知,在访问Controller中每个方法前,记录用户的操作日志。
Spring AOP使用步骤:
实现此案例需要按照如下步骤进行。
步骤一:创建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
使用Spring AOP环绕通知,在访问Controller中每个方法前,记录用户的操作日志。
Spring AOP使用步骤:
实现此案例需要按照如下步骤进行。
步骤一:创建方面组件
复用方面组件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
Spring 通过来AOP 实现前置,环绕,异常通知,注解(转)
原文:http://www.cnblogs.com/softidea/p/4738008.html