基于注解的Spring AOP入门、增强Advice实例
这篇文章简单通过一个例子,介绍几种增强的基本配置,以方便spring框架初学者对aop的代码结构有个清楚的了解认识。首先,spring支持aop编程,支持aspectJ的语法格式来表示切入点,切面,增强等,可以两种方式进行配置,一种是基于xml,一种是基于注解,本文介绍基于注解的集中增强的配置和使用。首先,在项目中引入spring的jar包和其他必备的常用jar包,还需引入一个aspectj的支持jar包,maven引用格式为:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency>
版本号自己决定,这样做,可以在JAVA代码中使用如@Aspect注解等,另外,需要在资源配置xml文件中,增加说明:
<!-- 自动注册service --> <context:component-scan base-package="com.minlz.aop.anno" /> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
这样子,就可以自动扫描被注解的aop切面,切入点等。
其他没有介绍的配置选项,参照普通spring项目的环境配置搭建即可,不再啰嗦,下面展示简单的栗子,来说明该如何通过代码和注解配置AOP的组件。
首先是一个主业务逻辑,我们有一个接口和一个实现类,实现类中的方法将传入的参数的绝对值返回,但是如果参数为0,则抛出异常信息。代码如下:
接口:
package com.minlz.aop.anno;
/**
* @author Bruce.Min
* @date 2016年7月20日
*/
public interface IAnnoService {
/**
* 主业务
* @param param
* @return
*/
int mainService(int param);
}
实现类为:
package com.minlz.aop.anno;
import org.springframework.stereotype.Component;
/**
* @author Bruce.Min
* @date 2016年7月20日
*/
@Component
public class AnnoService implements IAnnoService {
public int mainService(int param) {
if(param == 0) {
throw new RuntimeException("参数为0");
}
System.out.println("主业务,参数:" + param);
return Math.abs(param);
}
}
然后就是我们的切面实体了:
package com.minlz.aop.anno;
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.springframework.stereotype.Component;
/**
* @author Bruce.Min
* @date 2016年7月20日
*/
@Aspect
@Component
public class AnnoAspectBean {
/**
* 切入点声明 * args(param)表明参数,也可以通过增强方法中的JoinPoint获取
*/
private static final String ASPECT = "execution(* com.minlz.aop.anno.*.*(..)) and args(param)";
@Before(ASPECT)
public void before(JoinPoint point, int param) {
System.out.println("前置通知,参数为:" + param);
}
@After(ASPECT)
public void after(JoinPoint point, int param) {
System.out.println("后置通知,参数为:" + param);
}
/** * returning 表示主业务的返回值,名称和增强方法中的参数名匹配 */
@AfterReturning(value = ASPECT, returning = "retValue")
public void afterReturning(JoinPoint point, int param, int retValue) {
System.out.println("返回后通知,参数为: " + param + " ,返回值为:" + retValue);
}
@AfterThrowing(value = ASPECT, throwing = "ex")
public void afterThrowing(JoinPoint point, int param, Throwable ex) {
System.out.println("抛出异常通知,参数为: " + param + ", 异常信息: " + ex.toString());
}
@Around(ASPECT)
public Object around(ProceedingJoinPoint proPoint, int param) throws Throwable {
System.out.println("环绕通知开始,参数为:" + param);
Object retValue = proPoint.proceed();
System.out.println("环绕通知结束,参数为:" + param);
return retValue;
}
}
这里,关于切面的实体,有部分需要说明的地方:
1、@Aspect和@Component注解,两个都需要有,前者告之spring这是一个切面,后者告之spring该类被作为组件管理,如果不在资源配置xml中声明该bean且不使用@Component注解,则AOP不会生效。
2、所有的增强方法,都可以传入一个类型为JoinPoint或者ProceddingJoinPoint类型的切入点参数,通过该参数可以获取目标方法和目标方法参数等信息,也可以通过上面代码示例获取方法参数,方法抛出异常和返回值
现在万事俱备,我们写个测试类来测试上面代码的运行结果:
package com.minlz.test.aop;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.minlz.aop.anno.IAnnoService;
/**
* @author Bruce.Min
* @date 2016年7月20日
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-aop-anno.xml")
public class AopAnnoTest {
@Autowired
private IAnnoService iAnnoService;
@Test
public void testAnnoAop() {
iAnnoService.mainService(-1); //iAnnoService.mainService(0);
} }
如果参数为-1,则运行结果为:

通过结果可以知道,环绕通知发生在前置通知之前,在后置通知之前的,返回值增强顺序为最后。
如果,把参数改成0,则会抛出异常,那么会有哪些增强还能够继续运行的?结果如下:

可以看到,进入主业务之前,环绕通知前部分和前置通知正常运行,然后主业务抛出异常信息,主业务“完成”,后置通知启动,再接着异常增强运行,但是环绕通知后部分和返回值增强都没有运行!
总结:
本文只是简单介绍了集中增强的配置和使用,实际使用过程中,可能面临复杂的逻辑,但是原理不变,了解了每种增强的运行时机和结果,综合使用便不是问题。
PS:如有错误,还请各位赐教,不胜感激!
基于注解的Spring AOP入门、增强Advice实例的更多相关文章
- 基于注解的Spring AOP的配置和使用
摘要: 基于注解的Spring AOP的配置和使用 AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不 ...
- 基于注解的Spring AOP示例
基于注解的Spring AOP示例 目录 在XML配置文件中开启 @AspectJ 支持 声明切面及切入点 声明通知 测试 结语 在XML配置文件中开启 @AspectJ 支持 要使用Spring的A ...
- 基于注解的Spring AOP的配置和使用--转载
AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...
- 基于注解的Spring AOP拦截含有泛型的DAO
出错场景 1.抽象类BaseDao public abstract class BaseDao<T> { public BaseDao() { entityClass = (Class&l ...
- (转)使用Spring的注解方式实现AOP入门
http://blog.csdn.net/yerenyuan_pku/article/details/52865330 首先在Eclipse中新建一个普通的Java Project,名称为spring ...
- Spring Aop(二)——基于Aspectj注解的Spring Aop简单实现
转发地址:https://www.iteye.com/blog/elim-2394762 2 基于Aspectj注解的Spring Aop简单实现 Spring Aop是基于Aop框架Aspectj实 ...
- 基于注解的Spring多数据源配置和使用(非事务)
原文:基于注解的Spring多数据源配置和使用 1.创建DynamicDataSource类,继承AbstractRoutingDataSource package com.rps.dataSourc ...
- Spring:基于注解的Spring MVC
什么是Spring MVC Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据.业务与展现进行分离.从这样一个角度来说,Spring MVC ...
- Spring笔记07(Spring AOP的通知advice和顾问advisor)
1.Spring AOP的通知advice 01.接口代码: package cn.pb.dao; public interface UserDao { //主业务 String add(); //主 ...
随机推荐
- 在cygwin部署hadoop出现的问题:$ ./bin/hadoop version 显示错误: 找不到或无法加载主类 org.apache.hadoop.util.VersionInfo
解决方案 找到hadoop主目录的bin文件夹下的hadoop文件,将倒数第二行 exec "$JAVA" $JAVA_HEAP_MAX $HADOOP_OPTS $CLASS & ...
- Reverse Core 第一部分 代码逆向技术基础
@date: 2016/10/14 <逆向工程核心原理>笔记 记录书中较重要的知识,方便回顾 ps. 因有一些逆向基础,所以我本来就比较熟悉的知识并未详细记录 第一章 关于逆向工程 目标, ...
- C++ Bitstream类
从raknet上剥下来的 比较适用于前后端通讯,可以对BitStream进行二次封装,方便使用. BitStream.h: #ifndef __BITSTREAM_H #define __BITSTR ...
- Target runtime com.genuitec.runtime.generic.jee60 is not defined
转载自:http://jingyan.baidu.com/article/d7130635338e3f13fdf47518.html 用eclipse加载别人的工程,报错Target runtime ...
- js方法入参或局部变量和全局变量重名,用来赋值全局变量会失败
今天遇到个bug,最后终于知道原因了,js方法入参和全局变量重名,用入参赋值全局变量失败,就是说方法入参不能和全局变量重名. 现在下面的例子也说明,局部变量和全局变量不可以同名不光是入参,只要同名赋值 ...
- javaScript判断浏览器类型
<script type="text/javascript"> function getBrowserInfo(){ var OsObject=navigator.us ...
- 各种webservice调用地址
http://www.webxml.com.cn/zh_cn/web_services.aspx
- java程序性能优化
一.避免在循环条件中使用复杂表达式 在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快. 例子: import java.util ...
- 数据复制与AA双活(1)
最开始有些概念需要弄明白: 1. 什么是RPO? Wiki: https://en.wikipedia.org/wiki/Recovery_point_objective A recovery poi ...
- Linux C编程学习之开发工具3---多文件项目管理、Makefile、一个通用的Makefile
GNU Make简介 大型项目的开发过程中,往往会划分出若干个功能模块,这样可以保证软件的易维护性. 作为项目的组成部分,各个模块不可避免的存在各种联系,如果其中某个模块发生改动,那么其他的模块需要相 ...