Spring中的AOP的使用与JDK代理/cglib代理密切相关,与代理模式相关的内容的我的上篇博客Java设计模式–代理模式与JDK动态代理,cglib动态代理中有仔细的分析

一.AOP的概念

AOP即Aspect Oriented Programming,译为:面向切面编程,AOP技术是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是Spring框架中的一个重要内容,也是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率

二.AOP面向切面编程的目的及意义

AOP即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP通过封装、继承、多态等概念来建立起来的对象层次结构是一种纵向的关系。但是大型项目中有很多需要进行横向关系的抽象,比如日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术正是用来弥补OOP不足的一项技术,AOP对项目代码进行横向抽取,将多个类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面,在实际项目中的体现就是那些与业务无关,却为业务模块所共同调用的逻辑或责任。
通过AOP实现横向抽取后可以减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

三.Spring框架中AOP思想的应用

使用了AOP思想的Spring使得开发者能在不修改源码的情况下对程序进行功能增强。在Spring框架中,AOP切面编程主要用在事务处理,权限控制,日志记录,性能监控方面

2.1 AOP编程的相关概念:

Joinpoint(连接点)
所谓连接点是指那些被拦截到的点。在Spring框架中,连接点指的是方法,因为Spring只支持方法类型的连接点
Pointcut(切入点)
所谓切入点是指我们要对哪些Joinpoint进行拦截,目标类中所有的方法都是连接点,只有需要进行功能增强的方法是切入点,即切入点是连接点的子集
Advice(通知/增强)
所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。通知是切面要完成的功能,通知分为前置通知,后置通知,异常通知,最终通知,环绕通知5种。通知就是对目标方法的功能扩展,又被称作增强
Introduction(引介)
引介是一种特殊的通知,在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field。
Target(目标对象)
代理对象的目标对象
Proxy(代理)
一个类被AOP织入增强后,就产生一个结果代理类
Aspect(切面)
是切入点和通知(引介)的结合
Weaving(织入)
目标对象进行功能增强并创建代理对象的过程。Spring采用动态代理(包括JDK代理和cglib代理)进行织入,而AspectJ采用编译期织入和类装载期织入

2.2 使用Spring框架模拟AOP式事务处理过程:

2.2.1 模拟过程需要三步:

1)编写业务组件
2)编写通知,即对业务组件的增强功能。同时在Spring配置文件中配置通知
3)定义切入点,一个切入点可能横切多个业务组件

2.2.2 模拟程序:

1)业务层,用来处理业务逻辑

public interface UserService {void save();
}
public class UserServiceImpl implements UserService {@Overridepublic void save() {System.out.println("保存用户!");}
}

2)通知,通知的作用是对目标类进行增强

public class MyAdvice {//前置通知public void before(){System.out.println("这是前置通知!!");}//后置通知public void afterReturning(){System.out.println("这是后置通知(如果出现异常不会调用)!!");}//环绕通知,方法的参数是ProceedingJoinPoint,即连接点,在这里连接点是目标类public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("这是环绕通知之前的部分!!");//调用目标方法Object proceed = pjp.proceed();System.out.println("这是环绕通知之后的部分!!");return proceed;}//异常通知public void afterException(){System.out.println("出事啦!出现异常了!!");}//后置通知public void after(){System.out.println("这是后置通知(出现异常也会调用)!!");}
}

3)Spring配置文件,使用IOC和DI管理业务类,并配置切点和通知

<!-- 1.配置目标对象 -->
<bean name="userService" class="cn.spring.aop.service.UserServiceImpl" ></bean>
<!-- 2.配置通知对象 -->
<bean name="myAdvice" class="cn.spring.aop.e_annotationaop.MyAdvice" ></bean>
<!-- 3.配置切入点及通知 -->
<aop:config><!-- 配置切入点 --><!-- 没有指定具体的方法,所以ServiceImpl类中所有的方法都是切入点,即对ServiceImpl类中所有的方法进行增强 --><aop:pointcut expression="execution(* cn.spring.aop.service.*ServiceImpl.*(..))" id="pc"/><!-- 配置通知 --><aop:aspect ref="myAdvice" ><!-- 配置前置通知,一个名称为before的方法--><aop:before method="before" pointcut-ref="pc" /><!-- 配置后置通知 --><aop:after-returning method="afterReturning" pointcut-ref="pc" /><!-- 配置环绕通知 --><aop:around method="around" pointcut-ref="pc" /><!-- 配置异常通知 --><aop:after-throwing method="afterException" pointcut-ref="pc"/><!-- 配置后置通知 --><aop:after method="after" pointcut-ref="pc"/></aop:aspect></aop:config>
</beans>

3)测试类

//用于测试的注解
@RunWith(SpringJUnit4ClassRunner.class)、
//加载Spring配置文件
@ContextConfiguration("classpath:applicationContext_3.xml")
public class AOPTest {//注入(DI)一个userService类的实例@Resource(name="userService")private UserService us;//测试test()方法@Testpublic void test(){us.save();}
}

2.3 AOP事务处理过程解析:

2.3.1 切入点配置(切入点表达式)

使用Spring框架进行AOP编程时,要在Spring配置文件中配置切入点表达式,切入点表达式用来和目标类中的方法进行匹配,匹配成功的方法为切入点,切入点表达式的写法如下:

1)匹配cn.spring.service包下的UserServiceImpl类的名称为save的方法,方法必须是是public共有方法,没有方法参数,且返回值为void

public void cn.spring.service.UserServiceImpl.save()

2)匹配cn.spring.service包下的UserServiceImpl类的名称为save的方法,方法没有方法参数,且返回值为void,可以为共有或私有

void cn.spring.service.UserServiceImpl.save()

3)匹配cn.spring.service包下的UserServiceImpl类的名称为save的方法,方法没有方法参数,且返回值可以为任意类型,可以为共有或私有

* cn.spring.service.UserServiceImpl.save()

4)匹配cn.spring.service包下的UserServiceImpl类的所有方法,方法没有方法参数,且返回值可以为任意类型,可以为共有或私有

* cn.spring.service.UserServiceImpl.*()

5)匹配cn.spring.service包下的名称中带有ServiceImpl的类(即可以是UserServiceImpl类,也可以是OrderServiceImpl类)的所有方法,方法参数任意,且返回值可以为任意类型,可以为共有或私有

* cn.spring.service.*ServiceImpl.*(..)

6)匹配cn.spring.service包及其子包下的名称中带有ServiceImpl的类的方法(即可以是UserServiceImpl,也可以是OrderServiceImpl),方法参数任意,且返回值可以为任意类型,可以为共有或私有

* cn.spring.service..*ServiceImpl.*(..)

2.3.2 Spring框架实现AOP编程的方式

Spring框架内部使用动态代理来实现AOP编程,其中动态代理由两种方式,JDK动态代理和cglib动态代理,使用哪种动态代理由Spring框架自动选择,也可以在Spring的配置文件中设置使用JDK动态代理或cglib动态代理,将标签<aop:config>中的属性“proxy-target-class”设置为true则会使用cglib动态代理,设置为false则会使用JDK动态代理。使用过程中一般不会设置此属性,由Spring自动识别并选择

Spring-02-AOP切面编程相关推荐

  1. Spring中AOP切面编程学习笔记

    注解方式实现aop我们主要分为如下几个步骤: 1.在切面类(为切点服务的类)前用@Aspect注释修饰,声明为一个切面类. 2.用@Pointcut注释声明一个切点,目的是为了告诉切面,谁是它的服务对 ...

  2. Spring的AOP切面编程

    语言苍白无力,我们直接代码说话 package com.example.demo.aspect; import org.springframework.stereotype.Component; @C ...

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

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

  4. Aop切面编程原理和Spring实现

    Aop切面编程概念 AOP切面编程一般可以帮助我们在不修改现有代码的情况下,对程序的功能进行拓展,往往用于实现 日志处理,权限控制,性能检测,事务控制等 AOP实现的原理就是动态代理,在有接口的情况下 ...

  5. Spring中的AOP切面编程的三种实现方式

    文章目录 Spring中的AOP切面编程的三种实现方式 1.最基本AOP的实现 a.引入jar包 b.编写通知类,这里以后置通知和环绕通知类为例子进行说明 c.在SpringIOC容器中配置 d.测试 ...

  6. java切面类整合_SpringBoot2.x【五】整合AOP切面编程

    SpringBoot2.x[五]整合AOP切面编程 面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. ...

  7. SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Asp ...

  8. SpringAop篇 (2) Spring中的切面编程技术 AspectJ

    介绍 : AOP(Aspect Orient Programming) 既为面向切面编程. 它可以说是OOP编程的一种扩展与补充,可以较为友好的处理不同模块之间具有横向相关性质的一类问题,比如日志管理 ...

  9. spring框架学习 - 使用 Spring 的面向切面编程

    接上一篇博客:https://blog.csdn.net/qq_43605444/article/details/122029896?spm=1001.2014.3001.5502 七.使用 Spri ...

  10. Spring MVC AOP切面失效原因与处理

    Spring MVC AOP切面失效原因与处理 问题概述 AOP的两类实现 解决方案 方法一:用Autowired 注入自身的实例 方法二:从Spring上下文获取增强后的实例引用 方法三: 利用Ao ...

最新文章

  1. sqlserver中能用when_sqlserver中if语句顶替when.case.语句
  2. mybatis if test 用法_SpringBoot整合Mybatis-Plus 实战之动态SQL,Mybatis拿得出手的功能之一...
  3. epson me 1+只有主机能打印不能共享网络打印问题的处理
  4. java 短连接+MD5加密短链接
  5. 第二章从收入的预测分析开始
  6. 2.第一个页面amp;amp;分辨率和rpx
  7. [转]性能调优攻略(2)
  8. 计算机学数字电子基础知识,什么是数字电路?新手如何快速学习数字电路基础?...
  9. java 关键字 val,java关键字final用法知识点
  10. EPUB格式怎么转成MOBI格式
  11. 用Python编游戏
  12. 超详细Gulp打包seajs模块压缩合并,绝对对你项目有帮助 ~
  13. ffmpeg水印制作
  14. 6月6日重庆 减肥美容、无痕线雕提升技术精品班 (顾春英)
  15. TRIZ系列-创新原理-14~15-曲面化原理和动态性原理
  16. 背包问题-三种动态规划解法-逐步减少空间复杂度
  17. crontab: error renaming解决方法
  18. 万字长文详解 Go 程序是怎样跑起来的?| CSDN 博文精选
  19. TreeMap和TreeSet
  20. three.js嵌入可交互的普通页面

热门文章

  1. 事务对性能影响_mysql之事务
  2. java super.getclass_详解java中this.getClass()和super.getClass()的实例
  3. crawler4j源码学习(2):Ziroom租房网房源信息采集爬虫
  4. TensorFlow中数据的feed与fetch
  5. 基于相位一致性的边缘检测
  6. 算法题:(1) 有一个集合R = [a, b, c, d, e, f, g, h, i, j, k, l, m, n, ],....请写出求解这样的一个子集的通用算法。
  7. 堆排序(C++实现,非常简洁明了)
  8. iOS 中 UIView 和 CALayer 的关系
  9. WebSocket 实现链接 群聊(low low low 版本)
  10. QT 5 初学1 多窗口切分-续