Spring AOP 概述

AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程。可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP 可以说也是这种目标的一种实现。我们现在做的一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP 就实现了把这些业务需求与系统需求分开来做。这种解决的方式也称代理机制。

AOP里面的几个概念

1.切面(Aspect)
官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”。“切面”在ApplicationContext 中aop:aspect来配置。连接点(Joinpoint) :程序执行过程中的某一行为,例如,MemberService.get 的调用或者MemberService.delete 抛出异常等行为。

2、通知(Advice)
“切面”对于某个“连接点”所产生的动作。其中,一个“切面”可以包含多个“Advice”。

3、切入点(Pointcut)
匹配连接点的断言,在 AOP 中通知和一个切入点表达式关联。切面中的所有通知所关注的连接点,都由切入点表达式来决定。

4、目标对象(Target Object)
被一个或者多个切面所通知的对象。当然在实际运行时,SpringAOP 采用代理实现,实际 AOP 操作的是 TargetObject 的代理对象。

5、AOP 代理(AOP Proxy)
在 Spring AOP 中有两种代理方式,JDK 动态代理和 CGLib 代理。默认情况下,TargetObject 实现了接口时,则采用 JDK 动态代理,反之,采用 CGLib 代理。强制使用 CGLib 代理需要将 aop:config的 proxy-target-class 属性设为 true。

通知类型:

6、前置通知(Before Advice)
在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。ApplicationContext中在aop:aspect里面使用aop:before元素进行声明。

7、后置通知(After Advice)
当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext 中在aop:aspect里面使用aop:after元素进行声明。

8、返回后通知(After Return Advice)
在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext 中在aop:aspect里面使用元素进行声明。

9、环绕通知(Around Advice)
包围一个连接点的通知,类似 Web 中 Servlet 规范中的 Filter 的 doFilter 方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。ApplicationContext 中在aop:aspect里面使用aop:around元素进行声明。例如,ServiceAspect 中的 around 方法。

10、异常通知(After Throwing Advice)
在 方 法 抛 出 异 常 退 出 时 执 行 的 通 知 。 ApplicationContext 中 在 aop:aspect 里 面 使 用aop:after-throwing元素进行声明。

注:可以将多个通知应用到一个目标对象上,即可以将多个切面织入到同一目标对象。使用 Spring AOP 可以基于两种方式,一种是比较方便和强大的注解方式,另一种则是中规中矩的 xml配置方式。

先说注解,使用注解配置 Spring AOP 总体分为两步,第一步是在 xml 文件中声明激活自动扫描组件功能,同时激活自动代理功能:

<?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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"><context:component-scan base-package="com.stu"/><context:annotation-config /></beans>

第二步是为 Aspect 切面类添加注解:

//声明这是一个组件
@Component
//声明这是一个切面Bean,AnnotaionAspect是一个面,由框架实现的
@Aspect
public class AnnotaionAspect {private final static Logger log = Logger.getLogger(AnnotaionAspect.class);//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点//切点的集合,这个表达式所描述的是一个虚拟面(规则)//就是为了Annotation扫描时能够拿到注解中的内容@Pointcut("execution(* com.stu.aop.service..*(..))")public void aspect(){}/** 配置前置通知,使用在方法aspect()上注册的切入点* 同时接受JoinPoint切入点对象,可以没有该参数*/@Before("aspect()")public void before(JoinPoint joinPoint){log.info("before " + joinPoint);}//配置后置通知,使用在方法aspect()上注册的切入点@After("aspect()")public void after(JoinPoint joinPoint){log.info("after " + joinPoint);}//配置环绕通知,使用在方法aspect()上注册的切入点@Around("aspect()")public void around(JoinPoint joinPoint){long start = System.currentTimeMillis();try {((ProceedingJoinPoint) joinPoint).proceed();long end = System.currentTimeMillis();log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");} catch (Throwable e) {long end = System.currentTimeMillis();log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());}}//配置后置返回通知,使用在方法aspect()上注册的切入点@AfterReturning("aspect()")public void afterReturn(JoinPoint joinPoint){log.info("afterReturn " + joinPoint);}//配置抛出异常后通知,使用在方法aspect()上注册的切入点@AfterThrowing(pointcut="aspect()", throwing="ex")public void afterThrow(JoinPoint joinPoint, Exception ex){log.info("afterThrow " + joinPoint + "\t" + ex.getMessage());}}

测试代码

@ContextConfiguration(locations = {"classpath*:application-context.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class AnnotationTest {@AutowiredMemberService memberService;@Testpublic void test(){System.out.println("================");memberService.save(new Member());System.out.println("================");try {memberService.delete(1L);} catch (Exception e) {//e.printStackTrace();}}
}

测试结果

下面说下xml的简单使用

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsd               http://www.springframework.org/schema/aop               http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 注解驱动加上这句话 --><!--<aop:aspectj-autoproxy proxy-target-class="true"/>--><bean id="xmlAspect" class="com.stu.aop.aspect.XmlAspect"></bean><!--AOP配置 --><aop:config><!--声明一个切面,并注入切面Bean,相当于@Aspect --><aop:aspect ref="xmlAspect" ><!--配置一个切入点,相当于@Pointcut --><aop:pointcut expression="execution(* com.stu.aop.service..*(..))" id="simplePointcut"/><!--配置通知,相当于@Before、@After、@AfterReturn、@Around、@AfterThrowing --><aop:before pointcut-ref="simplePointcut" method="before"/><aop:after pointcut-ref="simplePointcut" method="after"/><aop:after-returning pointcut-ref="simplePointcut" method="afterReturn"/><aop:after-throwing pointcut-ref="simplePointcut" method="afterThrow" throwing="ex"/><aop:around pointcut-ref="simplePointcut"  method="around"/></aop:aspect></aop:config></beans>

XmlAspect就是一个切面类,具体实现就不贴出来了
通常情况下,表达式中使用”execution“就可以满足大部分的要求。表达式格式如下:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?

modifiers-pattern:方法的操作权限
ret-type-pattern:返回值
declaring-type-pattern:方法所在的包
name-pattern:方法名
parm-pattern:参数名
throws-pattern:异常

其 中 , 除 ret-type-pattern 和 name-pattern 之 外 , 其 他 都 是 可 选 的 。execution(* com.spring.service..(…))表示 com.spring.service 包下,返回值为任意类型;方法名任意;参数不限制的所有方法。
在上面的 Aspect 切面 Bean 中已经看到了,每个通知方法第一个参数都是 JoinPoint。其实,在 Spring中,任何通知(Advice)方法都可以将第一个参数定义为org.aspectj.lang.JoinPoint 类型用以接受当前连接点对象。JoinPoint 接口提供了一系列有用的方法, 比如 getArgs() (返回方法参数)、getThis() (返回代理对象)、getTarget() (返回目标)、getSignature() (返回正在被通知的方法相关信息)和 toString() (打印出正在被通知的方法的有用信息)。

详解Spring AOP原理相关推荐

  1. java切面不需要接口了吗_详解Spring AOP 实现“切面式”valid校验

    why: 为什么要用aop实现校验? answer: spring mvc 默认自带的校验机制 @Valid + BindingResult, 但这种默认实现都得在Controller方法的中去接收B ...

  2. 图文详解Spring AOP,你学会了吗?

    如果说 IOC 是 Spring 的核心,那么面向切面编程AOP就是 Spring 另外一个最为重要的核心,需要重点掌握@mikechen 本篇主要会详解以下六点: 1.AOP的定义 2.AOP的作用 ...

  3. 详解Spring工作原理

    1.spring原理 内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建.调用对象,Spring就是在运 ...

  4. 图文详解 Spring AOP,看完必懂!

    程序员的成长之路 互联网/程序员/技术/资料共享 关注 阅读本文大概需要 4 分钟. 来自:blog.csdn.net/duxd185120/article/details/109210224 学习一 ...

  5. java中MVC原理详解,Spring MVC 原理总结

    1. 什么是MVC? MVC是一种架构模式 --- 程序分层,分工合作,既相互独立,又协同工作 MVC是一种思考方式 --- 需要将什么信息展示给用户? 如何布局? 调用哪些业务逻辑? MVC流程图如 ...

  6. 多图详解Spring框架的设计理念与设计模式

    Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的JDBC应用做过报道.本文将从另外一个视角试图剖析出Spring框架的作者设计Spring框架的骨骼架构的 ...

  7. CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】

    每篇一句 重构一时爽,一直重构一直爽.但出了问题火葬场 前言 上篇文章通过我模拟的跨域请求实例和结果分析,相信小伙伴们都已经80%的掌握了CORS到底是怎么一回事以及如何使用它.由于Java语言中的w ...

  8. 详解spring事务失效和回滚失败的场景

    详解spring事务失效和回滚失败的场景 详解spring事务失效和回滚失败的场景 前言 一 .事务不生效 1.访问权限问题 2. 方法用final修饰 3.方法的内部调用 3.1 新加一个Servi ...

  9. java配置文件实现方式_java相关:详解Spring加载Properties配置文件的四种方式

    java相关:详解Spring加载Properties配置文件的四种方式 发布于 2020-4-29| 复制链接 摘记: 一.通过 context:property-placeholder 标签实现配 ...

  10. java中batch基础_详解Spring batch 入门学习教程(附源码)

    详解Spring batch 入门学习教程(附源码) 发布时间:2020-09-08 00:28:40 来源:脚本之家 阅读:99 作者:achuo Spring batch 是一个开源的批处理框架. ...

最新文章

  1. 如何实现label长度固定,文字分散分布的效果
  2. Objective-C 学习笔记15 NSProcessInfo
  3. mysql半复制_mysql半同步复制
  4. 泰拉瑞亚服务器config修改,泰拉瑞亚配置怎么修改_泰拉瑞亚配置修改方法介绍...
  5. java因子的计算方法是_JAVA分解质因子
  6. 百练 01 Charm Bracelet
  7. 转走出MFC窗口子类化迷宫
  8. python调用第三方接口获取数据_python调用接口,python接收post请求接口(附完整代码)...
  9. knn算法实例python_Python实现的knn算法示例
  10. 13凯越门锁继电器在哪里_汽车中控保险丝在哪里_汽车一年保险费_保险频道
  11. 桥接(Bridge)
  12. 《java编程思想》读书笔记(二)第五章(2)
  13. struts2 result随笔
  14. 深度学习(三)----算法岗面试题
  15. Java注释以及快捷键
  16. AI配音专家(文字转语音真人发声工具)官方中文版V1.0.5 | 文字转语音软件下载 | 这是一款阿里语音合成引擎且能把文字读出来的软件
  17. 备战秋招之数电模电知识点
  18. mac sz rz file tras
  19. cdr怎么把矩形去掉一个边_cdr怎么消除图形的边框?
  20. The operator ‘SUBTRACT‘ is not supported between objects of type ‘null‘ and ‘java.lang.Integer‘

热门文章

  1. c语言小车路径规划算法,基于路径规划的室内小车定位系统
  2. wxnativecallback.php,ectouch开发 | 糊涂虫
  3. imx6ul pinctrl 驱动浅析
  4. jmeter压力测试+badboy脚本录制
  5. 计算机用户名显示TEMP,windows7登陆创建TEMP临时个人配置文件夹解决方法-系统操作与应用 -亦是美网络...
  6. 10款超炫HTML5游戏 附游戏源码
  7. jQuery倒计时插件
  8. 软件评测师备考详细知识点
  9. KVM虚拟化技术基础框架
  10. 2022甘肃省安全员C证特种作业证考试题库及模拟考试