在《初识Spring》中我们了解到Spring支持AOP且可配置方法的前置曾强和后置曾强,但其实Spring支持多种曾强类型。下面同过一些例子来介绍Spring的几种常用的曾强(前置增强和后置曾强不再进行介绍,详情可参阅《初识Spring》这篇博客)。

异常抛出曾强

异常抛出曾强的特点是在目标方法抛出异常时织入曾强处理。首先我们要编写一个实现异常曾强代码的类,给类实现ThrowsAdvice接口。如下所示:

package cn.wz.aop;

import java.lang.reflect.Method;

import org.apache.log4j.Logger;
import org.springframework.aop.ThrowsAdvice;
public class ErrorLogger implements ThrowsAdvice {
Logger log=Logger.getLogger(ErrorLogger.class);
/**
* 实现异常曾强代码的方法
* @param method 目标方法名
* @param args 向目标方法传入的参数
* @param target 目标方法所在的类的实例
* @param e 目标方法内所抛出的异常对象
*/
public void afterThrowing(Method method,Object[] args,Object target,Exception e) {
log.error(method.getName()+"发生异常:"+e);
}
}

 

上述代码通过实现ThrowsAdvice接口实现异常抛出曾强,其中ThrowsAdvice接口中没有定义任何方法,但我们在定义异常抛出的曾强方法时必须遵守以下方法签名:

void afterThrowing([Method method,Object [] arguments,Object target,]Throwable ex)

这里Spring规定了方法名必须是“afterThrowing”。方法参数只有最后一个是必须的,前面三个参数是可选的,但是前面三个参数只能是要么都提供,要么都不提供!否则则无法实现曾强。下面编写测试类进行测试:

package cn.wz.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class ExceptionTest {
public static void main(String[] args) throws Exception {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
ExceptionTest bean = context.getBean("test",ExceptionTest.class);
bean.add();
} public void add() throws Exception {
throw new Exception("错误"); }
}

最终运行结果:

对于Spring配置文件的配置方法与前置增强和后置曾强的配置方法相同这里不再进行演示,

环绕曾强

环绕曾强在目标方法的前后都可以织入曾强处理。环绕增强是功能最强大的增强处理,Spring把目标方法的控制权全部交给了它。在环绕曾强处理中,可以获取或修改目标方法的参数,返回值,可以对它进行异常处理,甚至可以决定目标方法是否执行!

好了下面来看看如何实现环绕曾强吧。首先还是要定义实现环绕曾强代码的类,该类实现了MethodInterceptor接口的invoke()方法,在invoke()方法中编写曾强代码。

package cn.wz.aop;

import java.lang.reflect.Method;
import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
public class ErrorLogger implements MethodInterceptor {
Logger log=Logger.getLogger(ErrorLogger.class); public Object invoke(MethodInvocation arg0) throws Throwable {
Method method = arg0.getMethod();
Object[] arguments = arg0.getArguments();
Object target = arg0.getThis();
log.info("调用"+target+"的"+method.getName()+"方法。方法入参:"+Arrays.toString(arguments)); try {
Object result = arg0.proceed();
log.info("调用"+target+"的"+method.getName()+"方法。方法返回值:"+result);
return result;
} catch (Exception e) {
log.error(method.getName()+"方法异常:"+e);
}
return null;
}
}

上述代码通过MethodInterceptor接口实现了环绕增强。该接口要求实现invoke方法,其参数MethodInvocation不但疯转了目标方法及其入参数组,还封装了被代理的目标对象。通过proceed方法可以调用目标对象响应的方法,从而实现对目标方法的完全控制。借助异常抛出曾强的测试代码进行测试其运行结果如下:

使用注解实现曾强

除了实现Spring提供的特定接口外,Spring还可以通过集成AspectJ实现了以注解的方式定义增强类。大大减少了配置文件中的工作量。

注意:使用Aspectj是要确保JDK的版本是5.0或以上的版本,否则将无法使用注解技术,其次还要引入asm模块的jar包到项目中

前置曾强和后置曾强类:

package cn.wz.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; @Aspect
public class UserLogger {
private static final Logger log=Logger.getLogger(UserLogger.class);
@Before("execution(public void add())")
public void before(){
log.info("前置增强");
}
@AfterReturning("execution(public void add())")
public void afterReturning(){
log.info("后置增强");
}
}

在Spring配置文件中的配置如下:

异常抛出增强类:

package cn.wz.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect; @Aspect
public class Error_Logger {
private static final Logger log=Logger.getLogger(UserLogger.class);
@AfterThrowing(pointcut="execution(public void add())" ,throwing="e")
public void agterThrowing(JoinPoint jp,Exception e){
log.error(jp.getSignature().getName()+"发生异常:"+e);
}
}

环绕增强类:

package cn.wz.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class ArounsLogger {
private static final Logger log=Logger.getLogger(UserLogger.class);
@Around("execution(public void add())")
public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable{
System.out.println("前置增强");
Object obj = jp.proceed();//调用原始方法
System.out.println("后置增强");
return obj; }
}

SpringAOP使用扩展的更多相关文章

  1. 面向切面编程AOP

    本文的主要内容(AOP): 1.AOP面向切面编程的相关概念(思想.原理.相关术语) 2.AOP编程底层实现机制(动态代理机制:JDK代理.Cglib代理) 3.Spring的传统AOP编程的案例(计 ...

  2. Spring第二天

    Spring第二天 整体课程安排(3天+2天): 第一天:Spring框架入门.IoC控制反转的配置管理.Spring Web集成.Spring Junit集成. 第二天:Spring AOP面向切面 ...

  3. ssm单项目整合

    目录 前言 创建maven项目 添加依赖 配置文件 总览 jdbc配置 mybatis配置 dao层配置 service层配置 事务配置 controller配置 web.xml 使用 前言 spri ...

  4. SpringAOP详解(转载大神的)

    AOP(Aspect-Oriented Programming)这个东西,名字与 OOP 仅差一个字母,其实它是对 OOP 编程方式的一种补充,并非是取而代之.翻译过来就是"面向方面编程&q ...

  5. Spring-AOP实践 - 统计访问时间--StopWatch

    公司的项目有的页面超级慢,20s以上,不知道用户会不会疯掉,于是老大说这个页面要性能优化.于是,首先就要搞清楚究竟是哪一步耗时太多. 我采用spring aop来统计各个阶段的用时,其中计时器工具为S ...

  6. Spring-AOP用法总结

    前言     Spring AOP的实现方法很多,在项目开发中具体采用什么方式,需要按实际情况来选择,每一种的用法,有其一定的实用价值,所以本文将各种使用方法进行了具体实现.主要包括Advice的be ...

  7. SpringAop详解

    近几天学习了一下SpringAop在网上找了一些资料,此链接为原文链接http://www.cnblogs.com/xrq730/p/4919025.html AOP AOP(Aspect Orien ...

  8. 扩展Spring切面功能

    概述 Spring的切面(Spring动态代理)在Spring中应用十分广泛,例如还有事务管理,重试等等.网上介绍SpringAop源码很多,这里假设你对SpringAop有基本的了解.如果你认为Sp ...

  9. springaop——AspectJ不可不知的细节

    springaop简介 springaop是spring对AOP技术的具体实现,它是spring框架的核心技术.springaop底层使用JDK动态代理或CGLIB动态代理技术实现. 应用场景: 在多 ...

随机推荐

  1. [WPF实用技巧]如何使WPF的TreeView节点之间有连线

    示例代码:TreeViewEx.zip 原文地址:http://www.codeproject.com/Tips/673071/WPF-TreeView-with-WinForms-Style-Fom ...

  2. 控件UI性能调优 -- SizeChanged不是万能的

    简介 我们在之前的“UWP控件开发——用NuGet包装自己的控件“一文中曾提到XAML的布局系统 和平时使用上的一些问题(重写Measure/Arrange还是使用SizeChanged?),这篇博文 ...

  3. Hadoop开发第4期---分布式安装

    一.复制虚拟机 由于Hadoop的集群安装需要多台机器,由于条件有限,我是用虚拟机通过克隆来模拟多台机器,克隆方式如下图所示

  4. 让gcc支持成员函数模板的trick

    让gcc支持成员函数模板的trick 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议   gcc 4.7.3 不支持成员 ...

  5. SOA服务设计与实现的几个语言无关的原则速记

    一.SOA定义 SOA即面向服务架构(Service-Oriented Architecture).在SOA中,一切皆服务.一个服务是通过消息交换来调用的程序,一个信息系统是共同完成一个特定任务的一组 ...

  6. 简单JavaScript模版引擎优化

    在上篇博客最简单的JavaScript模板引擎 说了一下一个最简单的JavaScript模版引擎的原理与实现,作出了一个简陋的版本,今天优化一下,使之能够胜任日常拼接html工作,先把上次写的模版函数 ...

  7. Javascript隐式转换

    乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...

  8. Laravel5.0学习--02 实例进阶

    本文以laravel5.0.22为例. 本节以新建一个简单的博客作为实例. 准备工作 数据库配置 .env文件(也可以直接修改config/database.php) DB_HOST=localhos ...

  9. Linux初学 - Elasticsearch环境安装

    下载 https://www.elastic.co/downloads/elasticsearch 安装 rpm -ivh 也可以双击rpm包安装 修改elastaticsearch host配置 修 ...

  10. Script Task 引用 package variable

    Script Task 能够使用C#代码进行编程,许多复杂的逻辑都可以使用C# 脚本来实现,不仅灵活,而且强大. 1,能够传递package variable 给 Script Task ,并且Scr ...