一、什么是AOP

引用一下维基百科的定义

面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计剖面导向程序设计)是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进行进一步分离,以提高程序代码的模块化程度。通过在现有代码基础上增加额外的通知(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块进行统一管理与装饰,如“对所有方法名以‘set*’开头的方法添加后台日志”。该思想使得开发人员能够将与代码核心业务逻辑关系不那么密切的功能(如日志功能)添加至程序中,同时又不降低业务代码的可读性。面向切面的程序设计思想也是面向切面软件开发的基础。

面向切面的程序设计将代码逻辑切分为不同的模块(即关注点(Concern),一段特定的逻辑功能)。几乎所有的编程思想都涉及代码功能的分类,将各个关注点封装成独立的抽象模块(如函数、过程、模块、类以及方法等),后者又可供进一步实现、封装和重写。部分关注点“横切”程序代码中的数个模块,即在多个模块中都有出现,它们即被称作“横切关注点(Cross-cutting concerns, Horizontal concerns)”。

日志功能即是横切关注点的一个典型案例,因为日志功能往往横跨系统中的每个业务模块,即“横切”所有有日志需求的类及方法体。而对于一个信用卡应用程序来说,存款、取款、帐单管理是它的核心关注点,日志和持久化将成为横切整个对象结构的横切关注点。

二、AOP相关术语

  • Joinpoint(连接点): 所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的 连接点。

  • Pointcut(切入点): 所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。

  • Advice(通知/增强): 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。 通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

  • Introduction(引介): 引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方 法或 Field。

  • Target(目标对象): 代理的目标对象。

  • Weaving(织入): 是指把增强应用到目标对象来创建新的代理对象的过程。 spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

  • Proxy(代理): 一个类被 AOP 织入增强后,就产生一个结果代理类。-

  • Aspect(切面): 是切入点和通知(引介)的结合。


三、使用注解实现spring AOP

首先是我们的业务逻辑类

public class MathCalculator {public int div(int i,int j){System.out.println("MathCalculator...div...");return i/j; }}

接着是我们的切面类

/*** 切面类* @author lfy* * @Aspect: 告诉Spring当前类是一个切面类**/
@Aspect
public class LogAspects {//抽取公共的切入点表达式//1、本类引用//2、其他的切面引用@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")public void pointCut(){};//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)@Before("pointCut()")public void logStart(JoinPoint joinPoint){Object[] args = joinPoint.getArgs();System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");}@After("com.atguigu.aop.LogAspects.pointCut()")public void logEnd(JoinPoint joinPoint){System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");}//JoinPoint一定要出现在参数表的第一位@AfterReturning(value="pointCut()",returning="result")public void logReturn(JoinPoint joinPoint,Object result){System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");}@AfterThrowing(value="pointCut()",throwing="exception")public void logException(JoinPoint joinPoint,Exception exception){System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");}/*@Around(value="pointCut()")public void myAround(ProceedingJoinPoint joinPoint) {// 方法之前,前置通知System.out.println("《方法之前:前置通知");try {// 方法执行时joinPoint.proceed(); // 执行方法// 方法执行之后:后置通知System.out.println("《方法执行之后:后置通知");} catch (Throwable e) {// 发生异常时System.out.println("《发生异常时:异常通知");} finally {// 最终通知System.out.println("《最终通知");}}*/}

接着是我们的配置类:

/*** AOP:【动态代理】*      指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;* * 1、导入aop模块;Spring AOP:(spring-aspects)* 2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)* 3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;*      通知方法:*          前置通知(@Before):logStart:在目标方法(div)运行之前运行*          后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)*          返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行*          异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行*          环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())* 4、给切面类的目标方法标注何时何地运行(通知注解);* 5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;* 6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)* [7]、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】*      在Spring中很多的 @EnableXXX;* * 三步:*  1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)*  2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)*  3)、开启基于注解的aop模式;@EnableAspectJAutoProxy*/
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {//业务逻辑类加入容器中@Beanpublic MathCalculator calculator(){return new MathCalculator();}//切面类加入到容器中@Beanpublic LogAspects logAspects(){return new LogAspects();}
}

最后是我们的测试类:

public class IOCTest_AOP {@Testpublic void test01(){AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);//1、不要自己创建对象
//      MathCalculator mathCalculator = new MathCalculator();
//      mathCalculator.div(1, 1);MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);mathCalculator.div(1, 1);applicationContext.close();}}

控制台打印结果:

div运行。。。@Before:参数列表是:{[1, 1]}
MathCalculator...div...
div结束。。。@After
div正常返回。。。@AfterReturning:运行结果:{1}

注释中已经解释的很详细了,不再赘述。


四、环绕通知

环绕通知的功能比较强大,它可以实现其他四种通知

具体代码也很同意理解,放开LogAspects中的myAround方法,为方便观察,可以注释掉其他四种通知.

我们写个测试方法测试一下。

这次我们除以0试试

mathCalculator.div(1, 0);

打印:

《方法之前:前置通知
MathCalculator...div...
《发生异常时:异常通知
《最终通知

注意:环绕通知需要执行目标方法,参数使用ProceedingJoinPoint joinPoint,其父类没有这个joinPoint.proceed();/方法。

转载于:https://www.cnblogs.com/heliusKing/p/11421135.html

spring AOP注解实现相关推荐

  1. Spring AOP注解方式实现

    简介 上文已经提到了Spring AOP的概念以及简单的静态代理.动态代理简单示例,链接地址:https://www.cnblogs.com/chenzhaoren/p/9959596.html 本文 ...

  2. Spring AOP注解为什么失效?90%Java程序员不知道

    转载自 Spring AOP注解为什么失效?90%Java程序员不知道 使用Spring Aop注解的时候,如@Transactional, @Cacheable等注解一般需要在类方法第一个入口的地方 ...

  3. java spring aop 注解包_Spring AOP 注解配置实例

    Spring AOP注解例子 一:导入相关jar包. 首先导入Spring的相关包(这里就不多说了,我这里是3.2.4版本的) 然后导入AOP注解的相关包(不是spring的包)aspectjrt-1 ...

  4. spring AOP注解失效原因

    目录 @Transactional @Async等注解不起作用 JDK动态代理 Spring AOP注解失效原因及解决 原因1:同一个类中,方法A调用方法B(方法B上加有注解),注解无效 原因2:AO ...

  5. spring aop 注解

    spring Aop 注解 Aop 术语 AOP 的特性术语,不同的翻译还会不一样,得在过程中理解 横切关注点:跨越程序多个模块的方法或功能.即与业务逻辑无关,但我们也要关注的部分,就是横切关注点.如 ...

  6. spring AOP注解含义

    spring AOP 的几个注解含义 @Aspect                                                              指定一个类为切面类 @P ...

  7. Spring AOP注解

    1.配置 <!-- 配置spring创建容器时要扫描的包--><context:component-scan base-package="com">< ...

  8. spring注解:spring aop注解详解

    一. AOP的基本概念 Aspect(切面):通常是一个类,里面可以定义切入点和通知 Pointcut(切点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式 JointPoint(连接点) ...

  9. 初学spring aop 注解遇到的问题

    初学spring,对spring注解这块了解不是很多,现在注解替代了xml配置文件,原来的bean id 去哪里了呢? //@Service//默认类名 @Service("rmb" ...

最新文章

  1. c语言统计输入文本不同字母单词数,【C语言统计不同单词个数编写一个程序,输入一个句子,然后统计-查字典问答网...
  2. 皮一皮:我也想做这样的房东,善解人意、为他人着想...
  3. 扎克伯格预言即将成真:计算机可解读图片内容
  4. FZU - 2218 Simple String Problem(状压dp)
  5. mysql查询网址_bootstrap+flask+mysql实现网站查询
  6. 史上最全的JFinal源码分析(不间断更新)
  7. 天河一号超级计算机研制成功,我国首台千万亿次超级计算机“天河一号”研制成功,其运..._简答题试题答案...
  8. python怎么爬取知乎回答并制作词云_爬虫|爬取微博动态
  9. 人之间的尊重是相互的_人与人之间要学会相互尊重
  10. 查看Linux占用内存/CPU最多的进程
  11. UGUI——RectTransform详解
  12. 计算机考博面试题,交大系统博士笔试和面试题目
  13. 创建可引导的 macOS High Sierra 安装 U 盘
  14. CSS display(显示)详解 与 visibility(可见性)详解[第七天]
  15. C++11之防止类型收窄
  16. spark系列11:RDD之间的依赖关系,窄依赖和宽依赖
  17. 计算机组成原理-原理篇:指令与运算-12理解电路:从电报机到门电路,我们如何做到“千里传信”?
  18. Js二代身份证号码正则验证
  19. 如何让网站在360搜索结果中显示“官网”标志?
  20. Java初学者练习题

热门文章

  1. OpenCV手部关键点检测(手势识别)代码示例
  2. 练习图200例图纸讲解_建筑安装工程图例及符号手册,最全数据整理,施工图纸从此无忧...
  3. 详细解读Python 递归函数!
  4. 我是如何拿到百度计算机视觉暑期实习offer的?百度面经(成功上岸!已拿offer)
  5. 解决python中出现IndentationError:unindent does not match any outer indentation level错误
  6. android 电视遥控 编程,Android编程调用红外线遥控功能示例
  7. ROS在类中发布和接受消息(标准消息)
  8. ubuntu Vim的退出命令
  9. 2014秋应用计算机,2014年秋计算机应用基础》期末试卷A(A3版).doc
  10. php 日期format不要零_PHP格式化日期用法代码,包括前导零示例