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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 本节主要内容:     1. Spring AOP前置通知案例     2. Spring AOP环绕通知案例     3. Spring AOP异常通知案例     4. Spring AOP注解使用案例   AOP是Aspect Oriented Programming的缩写,意思是面向方面...

本节主要内容:     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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
20天前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
|
2天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
8天前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
29 4
SpringBoot必须掌握的常用注解!
|
8天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
20 1
|
10天前
|
存储 缓存 Java
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
45 2
|
10天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
27 1
|
1天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
8 0
|
4天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
8 0
|
5天前
|
存储 安全 Java
springboot当中ConfigurationProperties注解作用跟数据库存入有啥区别
`@ConfigurationProperties`注解和数据库存储配置信息各有优劣,适用于不同的应用场景。`@ConfigurationProperties`提供了类型安全和模块化的配置管理方式,适合静态和简单配置。而数据库存储配置信息提供了动态更新和集中管理的能力,适合需要频繁变化和集中管理的配置需求。在实际项目中,可以根据具体需求选择合适的配置管理方式,或者结合使用这两种方式,实现灵活高效的配置管理。
8 0
|
17天前
|
存储 Java 数据管理
强大!用 @Audited 注解增强 Spring Boot 应用,打造健壮的数据审计功能
本文深入介绍了如何在Spring Boot应用中使用`@Audited`注解和`spring-data-envers`实现数据审计功能,涵盖从添加依赖、配置实体类到查询审计数据的具体步骤,助力开发人员构建更加透明、合规的应用系统。
下一篇
无影云桌面