SpringAOP的应用实例与总结
一:AOP的背景
面试的时候面试官让我解释一下什么是AOP,当时不懂,在路上就查了,AOP:面向切面的编程技术,困惑了,JAVA是OOP:面向对象的编程技术。那么自己就立刻查了几个为题:1、什么是面向切面的编程技术;2、为什么要面向切面的编程技术;3、与OOP是什么关系?
首先解释第二个问题:在我们平时的开发过程中,你肯定会遇到下面几个面:1)权限校验;2)业务的核心代码;3)记录日志。那么在@Service层采用代码累加的方法,那么结构就会如下。
@Service
public class myService{ @Resource
private CoreService coreService; @Resource
private LogService logService;
@Resource
private PropertyService propertyService; // 权限校验代码 //核心业务层代码 //记录日志的代码 // 异常的处理
}
从上面的代码结构中我们可以看出以下几个问题:
1.1、代码混乱:核心业务模块与其他非核心的代码交织在一起,大大影响了代码的模块独立性能,不利于代码的维护,而且分工不明确造成代码混乱。
1.2、冗余代码:其实权限的校验,异常的处理,日志的记录可以独立在一个模块给所有的服务公用,写在一起导致代码的分散和冗余。
因此面向切面的编程技术应运而生。
解释第一个问题:什么是面向切面的编程技术。切面与切点是几何上面的术语,用在这里可以这样理解:将核心业务代码过程比作一个柱体,其他的日志记录,权限校验等就像是横切核心业务的面,这些面需要完成一些非核心的业务。如下图:

从图中可以看出我们定义了多个切面,每个切面都完成各自的非核心的业务,一个切面上还可以完成多个非核心的业务。
1.3、第三个问题:与OOP是什么关系?
AOP的实现技术有多种,其中与Java无缝对接的是一种称为AspectJ的技术,Spring AOP 与AspectJ 实现原理上并不完全一致,但功能上是相似的。AOP的出现确实解决外围业务代码与核心业务代码分离的问题,但它并不会替代OOP,如果说OOP的出现是把编码问题进行模块化,那么AOP就是把涉及到众多模块的某一类问题进行统一管理(参考:关于 Spring AOP (AspectJ) 你该知晓的一切;其实我也想到了他们的关系,但是感觉没有这篇博客总结的很好)
二:AOP的核心概念
从上右图可以可以很好看到切面(Aspect)包含了切点(PointCut)、连接点(JoinPoint);额外还有通知(Advice),织入(Weaving),引入(Introduce)。
package springMVCmybatis.com.my.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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.springframework.core.annotation.Order;
@Aspect
// 切面执行顺序
@Order(3)
public class MyAopTest {
@Pointcut("execution(* springMVCmybatis..addController.addEmp(..))")
private void pointCutMethod() {
} @Pointcut("execution(* springMVCmybatis.com.my.aop.UserServiceImp.*(..))")
private void testAOP() {
}
/*
* 声明前置通知 ,JoinPont是srpring提供的静态变量,
* 通过joinPoint参数可以获得目标方法的类名,方法参数,方法名等信息,这个参数可有可无。
*/ @Before("pointCutMethod() || testAOP()")
public void doBefore(JoinPoint joinPoint) {
System.out.println("@Before:开始添加--order=3");
} //声明后置通知 ,如果result的类型与proceed执行的方法返回的参数类型不匹配那么就不会执行这个方法
@AfterReturning(pointcut = "pointCutMethod() || testAOP()", returning = "result")
public void doAfterReturning(String result) {
System.out.println("@AfterReturning:后置通知--order=3");
System.out.println("---" + result + "---");
} //声明例外通知
@AfterThrowing(pointcut = "pointCutMethod() || testAOP()", throwing = "e")
public void doAfterThrowing(Exception e) {
System.out.println("@AfterThrowing:例外通知--order=3");
System.out.println(e.getMessage());
} //声明最终通知
@After("pointCutMethod() || testAOP()")
public void doAfter() {
System.out.println("@After:最终通知--order=3");
}
/*
* 声明环绕通知
* 参数必须是ProceedingJoinPoint,通过该对象的proceed()方法来执行目标函数,
* proceed()的返回值就是环绕通知的返回值,proceedingJoinPoint是个接口,
* implement JoinPoint,所以也可以获得目标函数的类名,方法名等参数。
*/ @Around("pointCutMethod() || testAOP()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("@Around:进入方法---环绕通知--order=3");
Object o = pjp.proceed();
System.out.println("@Around:退出方法---环绕通知--order=3");
return o;
} }
上面是我写的一个例子,结合例子我们来看看这些核心的概念:
2.1、切面(Aspect):是一个类,里面定义了通知与切点。
2.2、切点(PointCut):表达式。就是告诉程序要在执行哪些核心业务的时候,执行非核心的业务。
2.3、通知(advice):五种通知方式:
@Before:前置通知,在调用目标方法之前执行通知定义的任务@After:后置通知,在目标方法执行结束后,无论执行结果如何都执行通知定义的任务@After-returning:后置通知,在目标方法执行结束后,如果执行成功,则执行通知定义的任务@After-throwing:异常通知,如果目标方法执行过程中抛出异常,则执行通知定义的任务@Around:环绕通知,在目标方法执行前和执行后,都需要执行通知定义的任务。
五种通知方式的执行顺序:
正常情况下的执行顺序: @Around:进入方法---环绕通知--order=3
@Before:开始添加--order=3
============执行业务方法findUser,查找的用户是:张三=============
@Around:退出方法---环绕通知--order=3
@After:最终通知--order=3
@AfterReturning:后置通知--order=3
---张三---
异常情况下的执行顺序: @Around:进入方法---环绕通知--order=3
@Before:开始添加--order=3
============执行业务方法addUser=============
@After:最终通知--order=3
@AfterThrowing:例外通知--order=3
null
三:切点表达式。
这个表达式有很多种,如方法签名表达式,类型签名表达式,还有其他的表达式,我只用过前面两个,其他的没用过,也不做介绍,如果这两种表达式不能解决问题的可以参考我参考的博客。
execution(<修饰符模式>?<返回类型模式><方法所在类的完全限定名称模式>(<参数模式>)<异常模式>?)
execution(modifiers-pattern? ret-type-pattern fully-qualified-class-name (param-pattern) throws-pattern?)
public String springMVCmybatic.com.my.aop.UserServiceImp(String a, int b) throw Exception{
}
- modifier-pattern?:表示方法的修饰符,可有可无;对应的就是 public
- ret-type-pattern:表示方法的返回值;对应的就是 String
- fully-qualified-class-name 方法所在类的完全限定名称;对应的就是 springMVCmybatic.com.my.aop.UserServiceImp
- param-pattern:表示方法的参数;对应的就是 String a, int b
- throws-pattern:表示方法抛出的异常,可有可无;对应的就是 throw Exception
3.2:&&,||,!
@Around("pointCutMethod() || testAOP()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("@Around:进入方法---环绕通知");
Object o = pjp.proceed();
System.out.println("@Around:退出方法---环绕通知");
return o;
}
表达式之间可以采用与,或,非的方式来过滤。
四:多个切点的执行顺序
上面的例子中,定义了order=3,重新创建一个切面,定义order=6,执行的结果是:
@Around:进入方法---环绕通知--order=3
@Before:开始添加--order=3
@Around:进入方法---环绕通知--order=6
@Before:开始添加--order=6
============执行业务方法findUser,查找的用户是:张三=============
@Around:退出方法---环绕通知--order=6
@After:最终通知--order=6
@AfterReturning:后置通知--order=6
---张三---
@Around:退出方法---环绕通知--order=3
@After:最终通知--order=3
@AfterReturning:后置通知--order=3
---张三--- @Around:进入方法---环绕通知--order=3
@Before:开始添加--order=3
@Around:进入方法---环绕通知--order=6
@Before:开始添加--order=6
============执行业务方法addUser=============
@After:最终通知--order=6
@AfterThrowing:例外通知--order=6
null
@After:最终通知--order=3
@AfterThrowing:例外通知--order=3
null
从结果中可以看出order越小越先执行,执行完了之后就order越小就越后推出。总结为下面的图:

【参考博客】
1、http://blog.csdn.net/javazejian/article/details/56267036/
2、http://blog.csdn.net/qqxhwwqwq/article/details/51678595
SpringAOP的应用实例与总结的更多相关文章
- spring-aop的简单实例注解版
项目结构如图,基本的spring的配置就不在赘述 1.首先编写自定义的切面类 package org.wu.test; import org.aspectj.lang.annotation.After ...
- SpringAOP的xml实例、注解形式实例、概念理解 以及execution表达式实例与概念说明
(1)Spring AOP的简单应用: -->AOP:(Aspect Orinted Programming)面向切面编程,用于具有横切逻辑的场合,如:访问控制,事务管理,性能检测,由切入点和增 ...
- SpringAOP原理分析
目录 Spring核心知识 SpringAOP原理 AOP编程技术 什么是AOP编程 AOP底层实现原理 AOP编程使用 Spring核心知识 Spring是一个开源框架,Spring是于2003年兴 ...
- spring来了-04-AOP
概述 aspect object programming 面向切面编程 功能:可以实现“业务代码”与“关注点代码”分离 关注点代码:就是指重复执行的代码 业务代码:核心的业务功能 运行期间,执行核心业 ...
- AOP面向切面编程
1.AOP Aop(aspect object programming)面向切面编程 功能: 让关注点代码与业务代码分离! 关注点 重复代码就叫做关注点: 切面 关注点形成的类,就叫切面(类)! 面向 ...
- Spring框架--AOP编程
2 手动实现AOP编程 AOP 面向切面的编程, AOP可以实现"业务代码"与"关注点代码"分离 // 保存一个用户 public void add(User ...
- Spring第六篇【Spring AOP模块】
前言 Spring的第五篇也算是AOP编程的开山篇了,主要讲解了代理模式-..本博文主要讲解Spring的AOP模块:注解方式和XML方式实现AOP编程.切入点表达式.. AOP的概述 Aop: as ...
- Spring【AOP模块】就是这么简单
前言 到目前为止,已经简单学习了Spring的Core模块.....于是我们就开启了Spring的AOP模块了...在讲解AOP模块之前,首先我们来讲解一下cglib代理.以及怎么手动实现AOP编程 ...
- Spring AOP学习笔记
Spring提供了一站式解决方案: 1) Spring Core spring的核心功能: IOC容器, 解决对象创建及依赖关系 2) Spring Web ...
随机推荐
- php7源码编译安装
以下以CentOS 7.2为例,安装php的运行环境,首先打开php官网http://php.net/点击导航栏的Downloads进入下载页面:http://php.net/downloads.ph ...
- Search Quick Union Find(图的存储结构)
Quick Find:适用于search频繁的情况 每个节点有一个id值,id相同表示两个节点相连通.在union时要将等于某一个id值都改成另一个id值 Quick Union: 适用于union频 ...
- Hadoop2.2.0多节点分布式安装及测试
众所周知,hadoop在10月底release了最新版2.2.很多国内的技术同仁都马上在网络上推出了自己对新版hadoop的配置心得.这其中主要分为两类: 1.单节点配置 这个太简单了,简单到只要懂点 ...
- Linux automake命令
1)automake 使用教程 http://loftor.com/archives/automake.html 2)configure.in Makefile.am解析 http://blog.cs ...
- springboot2.0整合jpa
在整合的遇到各种坑,以下是我整合的流程 1.pom.xml文件 <dependencies> <dependency> <groupId>org.springfra ...
- JAVA里的CAS算法简析
Atomic 从JDK5开始, java.util.concurrent包里提供了很多面向并发编程的类. 使用这些类在多核CPU的机器上会有比较好的性能.主要原因是这些类里面大多使用(失败-重试方式的 ...
- Dom4j入门
一.Dom4j API生成xml文件 @Test public void bulidXmlByDom4j(){ //创建document对象 Document document = DocumentH ...
- Djanjo 的app 模板路径 静态文件 完整版登录 新手三件套 以及orm
一: django中app的概念: 一个项目可以包含多个应用(app,类似于模块,主页打开多个模块就是多个app) 创建了app,要在配置文件中注册 二:模板路径配置: 1 templates文件夹 ...
- 网络爬虫--requests库中两个重要的对象
当我们使用resquests.get()时,返回的时response的对象,他包含服务器返回的所有信息,也包含请求的request的信息. 首先: response对象的属性有以下几个, r.stat ...
- Oracle学习笔记(十)
光标(游标)概念引入 就是一个结果集(查询或者其他操作返回的结果是多个时使用)定义一个光标 cursor c1 is select ename from emp: 从光标中取值 打开光标: --ope ...