一、什么是AOP?

Aspect Oriented Programming ,即面向切面编程

  • AOP是对面向对象编程的一个补充。
  • 它的目的是将复杂的需求分解为不同的切面,将散布在系统中的公共功能集中解决。
  • 它的实际含义是在运行时将代码切入到类的指定方法、指定位置上,将不同方法的同一个位置抽象为一个切面对象,并对该对象进行编程。

下面是AOP的一个示意图

二、AOP的优点和一些概念

1、AOP的优点
  • 降低模块之间的耦合度
  • 使系统更容易扩展
  • 更好的代码复用
  • 非业务代码更加集中,不分散,便于统一管理
  • 业务代码更加简洁纯粹,不掺杂其他的代码的影响
2、AOP中出现的一些概念
  • 切面:横切关注点,被模块化的抽象对象
  • 通知:切面对象完成的工作(非业务代码)
  • 目标:被通知的对象(即被横切的对象)
  • 代理:切面、通知、目标混合之后的对象
  • 连接点:通知要插入业务代码的具体位置(如Spring实现中的JoinPoint)
  • 切点:AOP通过切点定位到连接点

三、使用动态代理实现AOP

1、添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.11.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
2、创建一个计算器接口Cal,定义四个方法

动态代理的类的方法应当都由接口来实现,这样才方便使用动态代理对象执行方法

3、创建接口的实现类CalImpl

高耦合的写法,每次打印日志都要手动完成:

4、使用动态代理进行优化

上方代码中,日志信息和业务逻辑的耦合性很高,不利于代码的维护。使用AOP可以进行优化,我们可以使用动态代理实现AOP:

给业务代码找一个代理,打印日志信息的工作交给代理来做。这样的话业务代码就只需要关注自身业务即可。

(1)去掉手动输出的日志信息



(2).代理辅助类的编写和使用(动态代理的核心)

我们创建的并不是所谓的代理类,而是一个可以帮助我们返回代理对象的辅助类,这个辅助类有两个功能

  1. 接收委托对象并依次返回代理对象
  2. 处理代理对象调用方法的过程



    值得注意的是:
  • 注意别忘了给委托对象赋值的那一步
  • 创建代理动态代理对象时传入的方法保证了代理类拥有原类的全部功能
  • 调用代理对象的方法时会自动调用invoke方法

    (3)测试

四、使用Spring实现AOP

动态代理实现AOP比较复杂,不易理解。Spring框架对AOP进行了封装,使用Spring框架可以用面向对象的思想实现AOP。Spring框架中不需要创建辅助类,只需要创建一个切面对象,将所有的非业务代码在切面对象中完成即可(但实际上Spring框架底层依然会根据切面类和代理类来生成代理对象。)

1、添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.11.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.11.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
2、创建一个计算器接口Cal,定义四个方法

当使用Spring实现时,这一步非必须!直接在实体类里面定义方法也可

3、定义实体类,实现方法

注意需要加上Component注解把他交给IoC

4、创建切面类



类定义处的两个注解

  • @Aspect表示该类是一个切面类
  • @Component将该类的对象注入到IoC容器(切面类和实体类都需要加上这个注解)

方法处的注解

  • @Before表示方法执行的具体位置和时机是方法开始时

  • @After类似Before,不过位置是方法的最后

  • @AfterReturning在下文有作解释

  • @AfterThrowing在下文有作解释

5、在spring.xml中进行配置

  • context:component-scan指扫描com.pedro包中的所有类,如果该类同时添加了component注解,则将该类扫描IoC容器中。即IoC管理它的对象
  • aop:aspectj-autoproxy让Spring容器结合切面类和目标类自动生成代理对象
6、使用



用代理对象调用方法就会自动执行它本身的方法和切面类中的非业务代码

为什么类名首字母要小写?

当使用注解配置bean时,默认id(别名)就是首字母改为小写的类名。若想修改,就在实体类的注解处加上自定义的名字即可。如@Component("test"),这样的话在getBean的时候就可以使用自定义的别名了,即xx.getBean("test")

7、两个特殊的After注解

(1)AfterReturning

用于在获取返回值后执行一段非业务代码

注:因为有两个参数,这里的value标签名被标出,而上面的before、after等注解只有一个参数,所以省略了value

结合上面的其他注解,会输出:

div方法的参数是[6,2]
div方法执行完毕
div方法的结果是3

(2)AfterThrowing

切面类的AfterThrowing注解,用于在抛出异常后执行一段非业务代码



结合上面的其他注解,会输出:

div方法的参数是[6,0]
div方法执行完毕
div方法抛出的异常:java.lang.ArithmeticException: / by zero

2021.4.3

最新文章

  1. Spring 4 + Reactor Integration Example--转
  2. IIS内存溢出-设置IIS的应用程序池
  3. JAVA 8 默认方法-Default Methods
  4. js日期选择控件
  5. 【leetcode】Best Time to Buy and Sell Stock II
  6. 利用SQLiteOpenHelper来管理SQLite数据库 (转)
  7. 216. Combination Sum III
  8. URAL 1517 Freedom of Choice(后缀数组,最长公共字串)
  9. 微信小程序视频地址
  10. 最新xgboost python32位下安装xgboost
  11. HDU2602 (0-1背包问题)
  12. 回调函数的意义以及python实现
  13. BZOJ 1192 鬼谷子的钱袋
  14. notepad扩展搜索,正则搜索
  15. AngularJS 框架
  16. Best Cow Line---POJ 3617(贪心)
  17. Koa 框架常用知识点整理
  18. 【ASP.NET Core快速入门】(十五)MVC开发:ReturnUrl实现、Model后端验证 、Model前端验证
  19. Hi3516A开发--接触(转)
  20. 细说REST API

热门文章

  1. AIoT &amp; IoT
  2. website captcha
  3. Base 64 &amp; URL &amp; blob &amp; FileReader &amp; createObjectURL
  4. egg.js in action
  5. 线上 S1 故障是什么, 线上 S1 故障, 运维故障分级, 运维, 故障分级, P1 级别故障, 故障, P1 , S1
  6. 图解 git 流程
  7. emplace_back与push_back
  8. 防抖和节流及对应的React Hooks封装
  9. Vue学习笔记-jsonl转换显示工具JsonView安装及使用
  10. Docker 搭建nexus私服