spring 5.x 系列第4篇 —— spring AOP (代码配置方式)
文章目录
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all
一、说明
1.1 项目结构说明
- 切面配置位于com.heibaiying.config下AopConfig.java文件;
- 自定义切面位于advice下,其中CustomAdvice是标准的自定义切面,FirstAdvice和SecondAdvice用于测试多切面共同作用于同一个被切入点时的执行顺序;
- OrderService是待切入方法。
1.2 依赖说明
除了spring的基本依赖外,需要导入aop依赖包
<!--aop 相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-base-version}</version>
</dependency>
二、spring aop
2.1 创建待切入接口及其实现类
public interface OrderService {
Order queryOrder(Long id);
Order createOrder(Long id, String productName);
}
public class OrderServiceImpl implements OrderService {
public Order queryOrder(Long id) {
return new Order(id, "product", new Date());
}
public Order createOrder(Long id, String productName) {
// 模拟抛出异常
// int j = 1 / 0;
return new Order(id, "new Product", new Date());
}
}
2.2 创建自定义切面类
注:@Pointcut的值可以是多个切面表达式的组合。
/**
* @author : heibaiying
* @description : 自定义切面
*/
@Aspect
@Component //除了加上@Aspect外 还需要声明为spring的组件 @Aspect只是一个切面声明
public class CustomAdvice {
/**
* 使用 || , or 表示或
* 使用 && , and 表示与
* ! 表示非
*/
@Pointcut("execution(* com.heibaiying.service.OrderService.*(..)) && !execution(* com.heibaiying.service.OrderService.deleteOrder(..))")
private void pointCut() {
}
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
//获取节点名称
String name = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println(name + "方法调用前:获取调用参数" + Arrays.toString(args));
}
// returning 参数用于指定返回结果与哪一个参数绑定
@AfterReturning(pointcut = "pointCut()", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
System.out.println("后置返回通知结果" + result);
}
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知-前");
//调用目标方法
Object proceed = joinPoint.proceed();
System.out.println("环绕通知-后");
return proceed;
}
// throwing 参数用于指定抛出的异常与哪一个参数绑定
@AfterThrowing(pointcut = "pointCut()", throwing = "exception")
public void afterThrowing(JoinPoint joinPoint, Exception exception) {
System.err.println("后置异常通知:" + exception);
}
@After("pointCut()")
public void after(JoinPoint joinPoint) {
System.out.println("后置通知");
}
}
2.3 配置切面
/**
* @author : heibaiying
* @description : 开启切面配置
*/
@Configuration
@ComponentScan("com.heibaiying.*")
@EnableAspectJAutoProxy // 开启@Aspect注解支持 等价于<aop:aspectj-autoproxy>
public class AopConfig {
}
2.4 测试切面
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = AopConfig.class)
public class AopTest {
@Autowired
private OrderService orderService;
@Test
public void saveAndQuery() {
orderService.createOrder(1283929319L, "手机");
orderService.queryOrder(4891894129L);
}
/**
* 多个切面作用于同一个切入点时,可以用@Order指定切面的执行顺序
* 优先级高的切面在切入方法前执行的通知(before)会优先执行,但是位于方法后执行的通知(after,afterReturning)反而会延后执行
*/
@Test
public void delete() {
orderService.deleteOrder(12793179L);
}
}
2.5 切面执行顺序
多个切面作用于同一个切入点时,可以用@Order指定切面的执行顺序
优先级高的切面在切入方法前执行的通知(before)会优先执行,但是位于方法后执行的通知(after,afterReturning)反而会延后执行,类似于同心圆原理。

附: 关于切面表达式的说明
切面表达式遵循以下格式:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
- 除了返回类型模式,名字模式和参数模式以外,所有的部分都是可选的;
*,它代表了匹配任意的返回类型;()匹配了一个不接受任何参数的方法, 而(..)匹配了一个接受任意数量参数的方法(零或者更多)。 模式(*)匹配了一个接受一个任何类型的参数的方法。 模式(*,String)匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型。
下面给出一些常见切入点表达式的例子。
任意公共方法的执行:
execution(public * *(..))任何一个以“set”开始的方法的执行:
execution(* set*(..))AccountService接口的任意方法的执行:execution(* com.xyz.service.AccountService.*(..))定义在service包里的任意方法的执行:
execution(* com.xyz.service.*.*(..))定义在service包或者子包里的任意方法的执行:
execution(* com.xyz.service..*.*(..))在service包里的任意连接点(在Spring AOP中只是方法执行) :
within(com.xyz.service.*)在service包或者子包里的任意连接点(在Spring AOP中只是方法执行) :
within(com.xyz.service..*)实现了
AccountService接口的代理对象的任意连接点(在Spring AOP中只是方法执行) :this(com.xyz.service.AccountService)
更多表达式可以参考官方文档:Declaring a Pointcut
附:源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all
spring 5.x 系列第4篇 —— spring AOP (代码配置方式)的更多相关文章
- spring 5.x 系列第2篇 —— springmvc基础 (代码配置方式)
文章目录 一.搭建hello spring工程 1.1 项目搭建 1.2 相关注解说明 二.配置自定义拦截器 三.全局异常处理 四.参数绑定 4.1 参数绑定 4.2 关于日期格式转换的三种方法 五. ...
- spring 5.x 系列第18篇 —— 整合websocket (代码配置方式)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 项目模拟一个简单的群聊功能,为区分不同的聊 ...
- spring 5.x 系列第16篇 —— 整合dubbo (代码配置方式)
文章目录 一. 项目结构说明 二.项目依赖 三.公共模块(dubbo-ano-common) 四. 服务提供者(dubbo-ano-provider) 4.1 提供方配置 4.2 使用注解@Servi ...
- spring 5.x 系列第14篇 —— 整合RabbitMQ (代码配置方式)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 本用例关于rabbitmq的整合提供简单消 ...
- spring 5.x 系列第12篇 —— 整合memcached (代码配置方式)
文章目录 一.说明 1.1 XMemcached客户端说明 1.2 项目结构说明 1.3 依赖说明 二.spring 整合 memcached 2.1 单机配置 2.2 集群配置 2.3 存储基本类型 ...
- spring 5.x 系列第10篇 —— 整合mongodb (代码配置方式)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 配置文件位于com.heibaiying. ...
- spring 5.x 系列第17篇 —— 整合websocket (xml配置方式)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 项目模拟一个简单的群聊功能,为区分不同的聊 ...
- spring 5.x 系列第15篇 —— 整合dubbo (xml配置方式)
文章目录 一. 项目结构说明 二.项目依赖 三.公共模块(dubbo-common) 四. 服务提供者(dubbo-provider) 4.1 productService是服务的提供者( 商品数据用 ...
- spring 5.x 系列第13篇 —— 整合RabbitMQ (xml配置方式)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 本用例关于rabbitmq的整合提供简单消 ...
- spring 5.x 系列第11篇 —— 整合memcached (xml配置方式)
文章目录 一.说明 1.1 XMemcached客户端说明 1.2 项目结构说明 1.3 依赖说明 二.spring 整合 memcached 2.1 单机配置 2.2 集群配置 2.3 存储基本类型 ...
随机推荐
- spring应用实例
新建一个登陆页面:loginActionSupport.jsp,代码例如以下 <%@page contentType="text/html;charset=GBK" is ...
- 解决用户绕过Servlet直接访问jsp页面
解决用户绕过ActionServlet,直接访问jsp文件的问题 1.将所有jsp文件拷贝到WEB-INF目录下 因为WEB-INF目录中的内容不能直接访问,但能转发过来 项目结构图如下: 2.修改s ...
- silverlight,WPF动画终极攻略之白云飘,坐车去旅游篇(Blend 4开发)
原文:silverlight,WPF动画终极攻略之白云飘,坐车去旅游篇(Blend 4开发) 这章有点长,所以我分成了两章.这一章主要是准备工作,差不多算美工篇吧,这章基本不会介绍多少动画效果,主要讲 ...
- WPF与缓动(四) 弧形缓动
原文:WPF与缓动(四) 弧形缓动 WPF与缓动(四) 弧形缓动 ...
- style文件的指定
新建资源文件 写资源文件 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/prese ...
- HTTP协议学习 - 9 Method Definitions
# 前言 官方文档简略翻译.9 不是代表第九篇,而是在 RFC2616 中是第九篇.重要加粗,龟速翻译. # Method 9.3 GET The GET method means retrieve ...
- 理解 node.js 的事件循环
node.js 的第一个基本观点是,I/O 操作是昂贵的: 目前的编程技术最大的浪费来自等待 I/O 操作的完成.有几种方法可以解决这些对性能的影响(来自Sam Rushing): 同步:依次处理单个 ...
- PHP的MIPS交叉编译(CC=mipsel-openwrt-linux-uclibc-gcc,LD=mipsel-openwrt-linux-uclibc-ld)
物联网内存吃紧,跑JVM这种内存大户肯定吃不消.要跑还是跑C实现的服务,比如Nginx+PHP+SQLite.比如一些家用无线路由器,系统是Linux发行版OpenWrt,内存只有64MB到128MB ...
- 利用NPOI生成DOCX文档
首先安装NPOI控件: Install-Package NPOI 代码: using NPOI.OpenXmlFormats.Wordprocessing; using NPOI.XWPF.UserM ...
- Android零基础入门第16节:Android用户界面开发概述
原文:Android零基础入门第16节:Android用户界面开发概述 相信通过前面15期的学习,Android的开发环境已经基本掌握了,如果仍有问题,欢迎到Android零基础入门技术讨论微信群交流 ...