面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP)。OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面。方面实现了跨越多种类型和对象的关注点(例如事务管理)的模块化。(这些担忧在AOP文献中通常被称为“横切”问题。)

  Spring的一个关键组件是AOP框架。虽然Spring IoC容器不依赖于AOP(意味着不需要使用AOP),但AOP补充了Spring IoC以提供非常强大的中间件解决方案。

AOP概念

  AOP概念和术语

  • 切面(Aspect):跨越多个类别的关注点的模块化。事务管理是企业Java应用程序中横切关注点的一个很好的例子。在Spring AOP中,方面是通过使用常规类(基于模式的方法)或使用@Aspect注释(@AspectJ样式)注释的常规类来实现的 。

  • 加入点(Join point):程序执行期间的一个点,例如执行方法或处理异常。在Spring AOP中,连接点始终表示方法执行。

  • 通知(Advice):特定连接点的某个方面采取的操作。不同类型的通知包括“周围”,“之前”和“之后”通知。(通知类型将在后面讨论。)许多AOP框架(包括Spring)将通知建模为拦截器并在连接点周围维护一系列拦截器。

  • 切入点(Pointcut):匹配连接点的谓词。通知与切入点表达式相关联,并在切入点匹配的任何连接点处运行(例如,执行具有特定名称的方法)。由切入点表达式匹配的连接点的概念是AOP的核心,Spring默认使用AspectJ切入点表达式语言。

  • 引入(Introduction):代表类型声明其他方法或字段。Spring AOP允许向任何通知的对象引入新接口(以及相应的实现)。例如,可以使用简介使bean实现 IsModified接口,以简化缓存。(介绍被称为AspectJ社区中的类型间声明。)

  • 目标对象(Target object):由一个或多个方面通知的对象。也称为“通知对象”。由于Spring AOP是使用运行时代理实现的,因此该对象始终是代理对象。

  • AOP代理(AOP proxy):由AOP框架创建的对象,用于实现方面契约(通知方法执行等)。在Spring Framework中,AOP代理是JDK动态代理或CGLIB代理。

  • 编织(Weaving):将方面与其他应用程序类型或对象链接以创建通知对象。这可以在编译时(例如,使用AspectJ编译器),加载时间或在运行时完成。与其他纯Java AOP框架一样,Spring AOP在运行时执行编织。

  Spring AOP包括以下类型的通知:

  • 之前通知(Before advice):在连接点之前运行但无法阻止执行流程进入连接点的通知(除非它抛出异常)。

  • 返回后通知(After returning advice:):在连接点正常完成后运行的通知(例如,如果方法返回而不抛出异常)。

  • 抛出后通知(After throwing advice):如果方法通过抛出异常退出,则执行通知。

  • 之后(最终)通知(After (finally) advice):无论连接点退出的方式(正常或异常返回),都要执行通知。

  • 围绕通知(Around advice):围绕连接点的通知,例如方法调用。这是最有力的通知。around通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续加入点还是通过返回自己的返回值或抛出异常来快速通知的方法执行。

AOP代理

  Spring AOP默认使用AOP代理的标准JDK动态代理。这使得任何接口(或接口集)都可以被代理。

  Spring AOP也可以使用CGLIB代理。这是代理类而不是接口所必需的。默认情况下,如果业务对象未实现接口,则使用CGLIB。由于优化的做法是编程接口而不是类,业务类通常实现一个或多个业务接口。可以 强制使用CGLIB,在那些需要建议未在接口上声明的方法或需要将代理对象作为具体类型传递给方法的情况下

AOP示例

  1、新建一个目标对象类,AspectBiz.class

  1. package com.test.spring.aop.schema.advice.biz;
  2.  
  3. public class AspectBiz {
  4.  
  5. public void biz() {
  6. System.out.println("AspectBiz biz ....");
  7. // throw new RuntimeException("runtime exception ...");
  8. }
  9.  
  10. public void init(String bizName, int times) {
  11. System.out.println("AspectBiz init: " + bizName + " --- " + times);
  12. }
  13. }

  2、新建一个通知类,CustomAspect.class

  1. package com.test.spring.aop.schema.advice;
  2.  
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4.  
  5. public class CustomAspect {
  6.  
  7. public void before(){
  8. System.out.println("CustomAspect before ...");
  9. }
  10.  
  11. public void afterReturning(){
  12. System.out.println("CustomAspect afterReturning ...");
  13. }
  14.  
  15. public void afterThrowing(){
  16. System.out.println("CustomAspect afterThrowing ...");
  17. }
  18.  
  19. public void after(){
  20. System.out.println("CustomAspect after ...");
  21. }
  22.  
  23. public Object around(ProceedingJoinPoint pjp) throws Throwable{
  24.  
  25. Object obj = null;
  26. System.out.println("CustomAspect around1 ...");
  27. obj = pjp.proceed();
  28. System.out.println("CustomAspect around2 ...");
  29.  
  30. return obj;
  31. }
  32.  
  33. public Object aroundInit(ProceedingJoinPoint pjp, String bizName, int times) throws Throwable{
  34. System.out.println("CustomAspect aroundInit: " + bizName + " --- " + times);
  35. Object obj = null;
  36. System.out.println("CustomAspect around1 ...");
  37. obj = pjp.proceed();
  38. System.out.println("CustomAspect around2 ...");
  39.  
  40. return obj;
  41. }
  42.  
  43. }

  3、新建一个spring配置文件,spring-aop-schema-advice.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  8. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"
  9. >
  10.  
  11. <bean id="customAspect" class="com.test.spring.aop.schema.advice.CustomAspect"></bean>
  12.  
  13. <bean id="aspectBiz" class="com.test.spring.aop.schema.advice.biz.AspectBiz"></bean>
  14.  
  15. <aop:config>
  16. <aop:aspect id="customAspectAOP" ref="customAspect" >
  17.  
  18. <aop:pointcut id="customPointCut" expression="execution(* com.test.spring.aop.schema.advice.biz.*Biz.*(..))" />
  19. <aop:before method="before" pointcut-ref="customPointCut"/>
  20. <aop:after-returning method="afterReturning" pointcut-ref="customPointCut"/>
  21. <aop:after-throwing method="afterThrowing" pointcut-ref="customPointCut"/>
  22. <aop:after method="after" pointcut-ref="customPointCut"/>
  23. <aop:around method="around" pointcut-ref="customPointCut"/>
  24. <!--
  25. 参数环绕通知
  26. <aop:around method="aroundInit" pointcut="execution(* com.test.spring.aop.schema.advice.biz.AspectBiz.init(String, int)) and args(bizName, times)"/>
  27. -->
  28. <!--
  29. 1、简介允许一个切面声明一个实现指定接口的通知对象,并且提供了一个接口实现类来代表这些对象
  30. 2、<aop:aspect>中的<aop:declare-parents>元素声明该元素用于声明所匹配的类型拥有一个新的parent(因此得名)
  31.  
  32. <aop:declare-parents
  33. types-matching="com.test.spring.aop.schema.advice.biz.*(+))"
  34. implement-interface="com.test.spring.aop.schema.advice.Fit"
  35. default-impl="com.test.spring.aop.schema.advice.FitImpl"/>
  36. -->
  37. </aop:aspect>
  38.  
  39. </aop:config>
  40.  
  41. </beans>

  4、新建一个测试类

  1. package com.test.spring.test;
  2.  
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4.  
  5. import com.test.spring.aop.schema.advice.biz.AspectBiz;
  6.  
  7. public class TestSpringAOPAdvice {
  8.  
  9. public static void main(String[] args) {
  10.  
  11. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-schema-advice.xml");
  12. AspectBiz aspectBiz = (AspectBiz) context.getBean("aspectBiz");
  13. aspectBiz.biz();
  14.  
  15. }
  16.  
  17. }

  5、运行测试结果,如下

    

@AspectJ支持

  @AspectJ指的是将方面声明为使用注释注释的常规Java类的样式。作为AspectJ 5版本的一部分,AspectJ项目引入了@AspectJ样式 。

  要在Spring配置中使用@AspectJ方面,您需要启用Spring支持,以基于@AspectJ方面配置Spring AOP,并根据这些方面是否建议自动代理bean。通过自动代理,如果Spring确定bean被一个或多个方面建议,它会自动为该bean生成一个代理来拦截方法调用,并确保根据需要执行建议。

  使用Java配置启用@AspectJ支持

  1. @Configuration
  2. @EnableAspectJAutoProxy
  3. public class AppConfig {
  4.  
  5. }

  使用XML配置启用@AspectJ支持,要使用基于XML的配置启用@AspectJ支持,请使用该aop:aspectj-autoproxy 元素,如以下示例所示:

  1. <aop:aspectj-autoproxy/>

  使用参考: 【Spring】基于@Aspect的AOP配置

  

【Java】Spring之面向方面编程(AOP)(五)的更多相关文章

  1. Spring学习手札(二)面向切面编程AOP

    AOP理解 Aspect Oriented Program面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 但是,这种说法有些片面,因为在软件工程中,AOP的价值体现的并 ...

  2. Spring(4)——面向切面编程(AOP模块)

    Spring AOP 简介 如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用. AOP 即 Aspect Orien ...

  3. 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  4. 黑马----面向方面编程AOP

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA反射-面向方面编程AOP 一.面向方面的需求 有如下模型: 需要统计客户登录时间.使用系统情况,或系统运行日记等信息时, ...

  5. Spring IOP 面向切面编程

    Spring IOP  面向切面编程 AOP操作术语 Joinpoint(连接点):所谓连接点是指那些被拦截到的点.在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.(类里面 ...

  6. Spring框架学习笔记(2)——面向切面编程AOP

    介绍 概念 面向切面编程AOP与面向对象编程OOP有所不同,AOP不是对OOP的替换,而是对OOP的一种补充,AOP增强了OOP. 假设我们有几个业务代码,都调用了某个方法,按照OOP的思想,我们就会 ...

  7. Spring AOP: Spring之面向方面编程

    Spring AOP: Spring之面向方面编程 面向方面编程 (AOP) 提供从另一个角度来考虑程序结构以完善面向对象编程(OOP). 面向对象将应用程序分解成 各个层次的对象,而AOP将程序分解 ...

  8. Spring学习笔记:面向切面编程AOP(Aspect Oriented Programming)

    一.面向切面编程AOP 目标:让我们可以“专心做事”,避免繁杂重复的功能编码 原理:将复杂的需求分解出不同方面,将公共功能集中解决 *****所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现 ...

  9. Spring之控制反转——IoC、面向切面编程——AOP

      控制反转——IoC 提出IoC的目的 为了解决对象之间的耦合度过高的问题,提出了IoC理论,用来实现对象之间的解耦. 什么是IoC IoC是Inversion of Control的缩写,译为控制 ...

  10. Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP)

    在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式.@pd ...

随机推荐

  1. Pthon魔术方法(Magic Methods)-上下文管理

    Pthon魔术方法(Magic Methods)-上下文管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.上下文管理方法 __enter__: 进入与此对象相关的上下文.如果 ...

  2. php数字字母字符串比较

    <?php$a="12a";if($a==12){echo "good";}?>这种情况能输出good,字母在后时只比较前两位,认为是相等:字母在前 ...

  3. sqliteman install parameter

    .安装前准备 系统要求:linux Qt库版本:一般都有 .安装文件 官网自行下载 .安装 )这里用的pscp pscp .\sqliteman-.tar.gz root@192.168.30.140 ...

  4. java代码获取项目版本号实例

    package com.hzcominfo.application.etl.settings.web.controller.highconfig; import com.hzcominfo.appli ...

  5. 《逆袭团队》第九次团队作业【Beta】Scrum meeting 2

    项目 内容 软件工程 任课教师博客主页链接 作业链接地址 团队作业9:Beta冲刺与团队项目验收 团队名称 逆袭团队 具体目标 (1)掌握软件黑盒测试技术:(2)学会编制软件项目总结PPT.项目验收报 ...

  6. 字节序 —— Big Endian 和 Little Endian

    一.字节序 字节序指的是多字节的数据在内存中的存放顺序 内存有高地址端与低地址端.其中,低地址端既可以存放高位字节,也可以存放低位字节. Big Endian 是指低地址端 存放 高位字节. Litt ...

  7. ZOJ - 3265: Strange Game (优化 二分图匹配)

    pro:有一个长度为N的数组a[i],要求选择k[i]>0,使得b[i]=a[i]^k[i]%M中出现的不同数最多.N<=200, M<=1e9: sol:a^x%p的个数的有限的, ...

  8. kubectl kubernetes cheatsheet

    from : https://cheatsheet.dennyzhang.com/cheatsheet-kubernetes-a4 PDF Link: cheatsheet-kubernetes-A4 ...

  9. Learning Vector Quantization

    学习矢量量化. k近邻的缺点是你需要维持整个数据集的训练. 学习矢量量化算法(简称LVQ)是一种人工神经网络算法,它允许你选择要挂在多少个训练实例上,并精确地了解这些实例应该是什么样子. LVQ的表示 ...

  10. Oracle iops测试

    DECLARE  lat  INTEGER;  iops INTEGER;  mbps INTEGER;BEGIN  DBMS_RESOURCE_MANAGER.CALIBRATE_IO(4, 10, ...