springMVC之AOP
AOP(Aspect-Oriented Programming,面向切面编程)
切面(Aepect):横切关注点(跨越应用程序多个模块的功能)被模块化的对象;
通知(Advice):切面必须要完成的工作;
目标(Target):被通知的对象;
代理(Proxy):像目标对象应用通知之后创建的对象;
连接点(Joinpoint):程序执行的某个特殊位置,如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;想对点表示的方位。
切点(pointcut):每个类都拥有多个连接点,即连接点是程序类中客观存在的事务;
AOP通过切点定位到特定的连接点。
AOP的主要编程对象是切面(aopect),而切面模块化横切关注点。
在应用AOP编程时,仍需要定义公共功能,但可以明确这个功能在哪里,以什么方式应用,并且不必修改受影响的类,这样的话横切关注点就被模块化到特殊的对象(切面)里。
AOP的好处:
每个事物逻辑位于一个位置,代码不分散,便于维护和升级;
业务模块更简洁,值包含核心业务代码
1、基于AspectJ注解
(1)Maven引入依赖包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.1</version>
</dependency>
(2)在spring配置文件中添加aop的命名空间,同时配置使得项目支持Aop,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--使Spring支持自动检测组件,如注解的Controller -->
<context:component-scan base-package="com.parry.redisCluster.*" />
<!--*************** 支持aop **************** -->
<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
(3)实现一个日志切面
- 切面首先是IOC容器中的一个bean,即在切面类前加上标签@Component标签
- 切面还需要添加标签@Aspect标签,声明该类是一个切面
- 实现需要的通知,在方法之前添加如下的通知类型:
- @Before:前置通知,在方法前通知;
- @After :后置通知,在方法执行后通知;
- @AfterRunning:返回通知,在方法返回结果之后通知;
- @AfterThrowing:异常通知,在方法抛出异常之后通知;
- @Around:环绕通知,围绕着方法执行;
- 切入点表达式的书写:
- execution(* com.cn21.redisCluster.controller.*(..)) :第一个*表示任意的修饰符(public/private/protected)及任意的返回值(void/Object);第二个*表示任意的方法,‘..’表示任意数量的参数;
- execution(public * com.cn21.redisCluster.controller.*Controller.*(..)):表示com.cn21.redisCluster.controller包下+以Controller结尾的+公共的方法(public)的方法;
- execution(public void com.cn21.redisCluster.controller.*Controller.*(..)):表示com.cn21.redisCluster.controller包下+以Controller结尾的+公共的方法(public)+返回类型是void的方法;
- execution(public void com.cn21.redisCluster.controller.*Controller.*(int,..)):表示com.cn21.redisCluster.controller包下+以Controller结尾+公共的方法(public)+返回类型是void的类+第一个参数是int的方法;
- execution(public void com.cn21.redisCluster.controller.*Controller.*(int,int)):表示com.cn21.redisCluster.controller包下+以Controller结尾+公共的方法(public)+返回类型是void的类+第一个参数是int+第二个参数是int的方法;
- 可以在方法中声明一个类型为JoinPoint的参数,然后就可以访问链接细节,如方法名称和参数值;
import java.util.Arrays;
import java.util.List; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
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.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; @Aspect //该标签把LoggerAspect类声明为一个切面
@Order(1) //设置切面的优先级:如果有多个切面,可通过设置优先级控制切面的执行顺序(数值越小,优先级越高)
@Component //该标签把LoggerAspect类放到IOC容器中
public class LoggerAspect { /**
* 定义一个方法,用于声明切入点表达式,方法中一般不需要添加其他代码
* 使用@Pointcut声明切入点表达式
* 后面的通知直接使用方法名来引用当前的切点表达式;如果是其他类使用,加上包名即可
*/
@Pointcut("execution(public * com.parry.redisCluster.controller.*Controller.*(..))")
public void declearJoinPointExpression(){} /**
* 前置通知
* @param joinPoint
*/
@Before("declearJoinPointExpression()") //该标签声明次方法是一个前置通知:在目标方法开始之前执行
public void beforMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("this method "+methodName+" begin. param<"+ args+">");
}
/**
* 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值)
* @param joinPoint
*/
@After("declearJoinPointExpression()")
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("this method "+methodName+" end.");
}
/**
* 返回通知(在方法正常结束执行的代码)
* 返回通知可以访问到方法的返回值!
* @param joinPoit
*/
@AfterReturning(value="declearJoinPointExpression()",returning="result")
public void afterReturnMethod(JoinPoint joinPoint,Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("this method "+methodName+" end.result<"+result+">");
}
/**
* 异常通知(方法发生异常执行的代码)
* 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
* @param joinPoint
* @param ex
*/
@AfterThrowing(value="declearJoinPointExpression()",throwing="ex")
public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println("this method "+methodName+" end.ex message<"+ex+">");
}
/**
* 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数)
* 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法
* 且环绕通知必须有返回值,返回值即目标方法的返回值
* @param joinPoint
*/
@Around(value="declearJoinPointExpression()")
public Object aroundMethod(ProceedingJoinPoint point){ Object result = null;
String methodName = point.getSignature().getName();
try {
//前置通知
System.out.println("The method "+ methodName+" start. param<"+ Arrays.asList(point.getArgs())+">");
//执行目标方法
result = point.proceed();
//返回通知
System.out.println("The method "+ methodName+" end. result<"+ result+">");
} catch (Throwable e) {
//异常通知
System.out.println("this method "+methodName+" end.ex message<"+e+">");
throw new RuntimeException(e);
}
//后置通知
System.out.println("The method "+ methodName+" end.");
return result;
}
}
2、基于XML配置的AOP
(1)在spring配置文件中添加aop的命名空间,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!--使Spring支持自动检测组件,如注解的Controller -->
<context:component-scan base-package="com.parry.redisCluster.*" /> <!-- 配置切面的Bean -->
<bean id="validationAspect" class="com.cn21.redisCluster.aspect.ValidationAspect"></bean> <!-- 配置AOP -->
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut id="pointcut" expression="execution(!void com.parry.redisCluster.controller.*.*(..))" />
<!-- 配置切面及配置 -->
<aop:aspect order="3" ref="validationAspect">
<!-- 前置通知 -->
<aop:before method="beforMethod" pointcut-ref="pointcut"/>
<!-- 后置通知 -->
<aop:after method="afterMethod" pointcut-ref="pointcut"/>
<!-- 返回通知 -->
<aop:after-returning method="afterReturnMethod" pointcut-ref="pointcut" returning="result"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="pointcut" throwing="ex"/>
</aop:aspect>
</aop:config>
</beans>
(2)实现切面类:
package com.parry.redisCluster.aspect; import java.util.Arrays;
import java.util.List; import org.aspectj.lang.JoinPoint; public class ValidationAspect { /**
* 前置通知
* @param joinPoint
*/
public void beforMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("ValidationAspect this method "+methodName+" begin. param<"+ args+">");
}
/**
* 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值)
* @param joinPoint
*/
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("ValidationAspect this method "+methodName+" end.");
}
/**
* 返回通知(在方法正常结束执行的代码)
* 返回通知可以访问到方法的返回值!
* @param joinPoit
*/
public void afterReturnMethod(JoinPoint joinPoint,Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("ValidationAspect this method "+methodName+" end.result<"+result+">");
}
/**
* 异常通知(方法发生异常执行的代码)
* 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
* @param joinPoint
* @param ex
*/
public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println("ValidationAspect this method "+methodName+" end.ex message<"+ex+">");
}
}
springMVC之AOP的更多相关文章
- springMVC Aspect AOP 接口耗时统计
在接口开发中,我们通常需要统计接口耗时,为后续接口性能做统计.在springMVC中可以用它的aop来记录日志. 1.在spring配置文件中开启AOP <!--*************** ...
- SpringMVC集成AOP错误:java lang classnotfoundexception org aspectj lang joinpoint
记录自己出现的问题,Spring AOP 使用测试类测试没问题,在SpringMVC启动服务器时出现java lang classnotfoundexception org aspectj lang ...
- springmvc集成aop记录操作日志
首先说明一下,这篇文章只做了记录日志相关事宜 具体springmvc如何集成配置aop对cotroller进行拦截,请看作者的另一篇文章 http://www.cnblogs.com/guokai87 ...
- springmvc配置aop
直接看代码 springmvc中的配置aop对 controller和它的子包进行拦截 springmvc中的配置 <!--xml头部配置需要有这几行代码--> xmlns:aop=&qu ...
- springmvc配置AOP的两种方式
spingmvc配置AOP有两种方式,一种是利用注解的方式配置,另一种是XML配置实现. 应用注解的方式配置: 先在maven中引入AOP用到的依赖 <dependency> <gr ...
- SpringMVC利用AOP实现自定义注解记录日志
作者:飞翔的拖鞋up 推荐:彻底征服 Spring AOP 之 实战篇 推荐:jason_zhangz 本文抛砖引玉,并没有详细的介绍更全面的内容,通过一个例子让初次使用的人能够快速入门,简单的介绍一 ...
- springmvc使用aop心得
第一步:创建aop拦截类: @Component @Aspect public class ControllerSelectorInterceptor { @Before("executio ...
- 基于spring注解AOP的异常处理
一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...
- springmvc+spring-security+mybatis +redis +solar框架抽取
参考文章:Spring MVC 3 深入总结: 第二章 Spring MVC入门 —— 跟开涛学SpringMVC 参考博客:http://www.cnblogs.com/liukemng/categ ...
随机推荐
- KVM 介绍(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照 (Nova Instances Snapshot Libvirt)
学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...
- PS色调均化滤镜的快捷实现(C#源代码)。
photoshop色调均化功能通常是在进行修片处理前期比较常用的功能之一,其对扩展图像的对比度,增强视觉效果有一定的作用.在很多课本或者文章中,也称这种处理为灰度均衡化.直方图均衡化等等.算法原理都是 ...
- JustWeEngine - 轻量级游戏框架
JustWeEngine - 轻量级游戏框架 An easy open source Android game engine. Github地址 引擎核心类流程图 使用方法 引入Engine作为Lib ...
- 比较全的JavaScript倒计时脚本[xyytit]
需要做一个功能,给特定的活动或者商品添加一个倒计时提示,在网上找了好些方法,总结了比较好的一些方法,以备后用: 1. 比较长时间的倒计时(如:距离2014年还有0年, 0月, 30天, 9小时, 41 ...
- 在把webpack作为本地开发依赖安装的时候报错
在把webpack作为本地开发依赖安装的时候报错 Refusing to install webpack as a dependency of itself 原因是package.json里的name ...
- JS中NULL和Undefined的区别
NULL是表示一个”无“的对象,转换成数值为0:undefined是一个“无”的原始值,转为数值为NaN: 当声明的变量还未被初始化时,变量的默认值为undefined: null用来表示尚未存在的对 ...
- 单机多实例Tomcat部署
单机单用户基础上, 如何运行多个tomcat实例. 首先是tomcat的目录结构 bin – 包含所有运行tomcat的二进制和脚本文件 lib – 包含tomcat使用的所有共享库 c ...
- C#输出log信息
在写程序的过程中,有时候我们需要添加一些log信息,这个时候,可以采用下面的方法来实现. public static void WriteLog(string ExtraMsg, Exception ...
- MVC中如何设置路由指定默认页
MVC中怎么设置默认页,在webform中 只要右键设置起始页就可以,但MVC中却没有这个功能,其实MVC更简单 如下: Login是控制器,Index 是动作 在全局Global.asax中改动下即 ...
- 【转】让Bootstrap 3兼容IE8浏览器
FROM : http://www.ijophy.com/2014/05/bootstrap3-compatible-with-ie8.html 最近在研究Bootstrap(官方,Github)这个 ...