AOP如何实现及实现原理

概述:

最近在开发中遇到了一个刚好可以用AOP实现的例子,就顺便研究了AOP的实现原理,把学习到的东西进行一个总结。文章中用到的编程语言为kotlin,需要的可以在IDEA中直接转为java。 这篇文章将会按照如下目录展开:

  • AOP简介
  • 代码中实现举例
  • AOP实现原理
  • 部分源码解析

1. AOP简介

相信大家或多或少的了解过AOP,都知道它是面向切面编程,在网上搜索可以找到很多的解释。这里我用一句话来总结:AOP是能够让我们在不影响原有功能的前提下,为软件横向扩展功能。 那么横向扩展怎么理解呢,我们在WEB项目开发中,通常都遵守三层原则,包括控制层(Controller)->业务层(Service)->数据层(dao),那么从这个结构下来的为纵向,它具体的某一层就是我们所说的横向。我们的AOP就是可以作用于这某一个横向模块当中的所有方法。

我们在来看一下AOP和OOP的区别:AOP是OOP的补充,当我们需要为多个对象引入一个公共行为,比如日志,操作记录等,就需要在每个对象中引用公共行为,这样程序就产生了大量的重复代码,使用AOP可以完美解决这个问题。

接下来介绍一下提到AOP就必须要了解的知识点:

  • 切面:拦截器类,其中会定义切点以及通知
  • 切点:具体拦截的某个业务点。
  • 通知:切面当中的方法,声明通知方法在目标业务层的执行位置,通知类型如下:
    1. 前置通知:@Before 在目标业务方法执行之前执行
    2. 后置通知:@After 在目标业务方法执行之后执行
    3. 返回通知:@AfterReturning 在目标业务方法返回结果之后执行
    4. 异常通知:@AfterThrowing 在目标业务方法抛出异常之后
    5. 环绕通知:@Around 功能强大,可代替以上四种通知,还可以控制目标业务方法是否执行以及何时执行

2. 代码中实现举例

上面已经大概的介绍了AOP中需要了解的基本知识,也知道了AOP的好处,那怎么在代码中实现呢?给大家举个例子:我们现在有个学校管理系统,已经实现了对老师和学生的增删改,又新来个需求,说是对老师和学生的每次增删改做一个记录,到时候校长可以查看记录的列表。那么问题来了,怎么样处理是最好的解决办法呢?这里我罗列了三种解决办法,我们来看下他的优缺点。

 

-最简单的就是第一种方法,我们直接在每次的增删改的函数当中直接实现这个记录的方法,这样代码的重复度太高,耦合性太强,不建议使用。

-其次就是我们最长使用的,将记录这个方法抽离出来,其他的增删改调用这个记录函数即可,显然代码重复度降低,但是这样的调用还是没有降低耦合性。

-这个时候我们想一下AOP的定义,再想想我们的场景,其实我们就是要在不改变原来增删改的方法,给这个系统增加记录的方法,而且作用的也是一个层面的方法。这个时候我们就可以采用AOP来实现了。

我们来看下代码的具体实现:

  1. 首先我定义了一个自定义注解作为切点
@Target(AnnotationTarget.FUNCTION)  //注解作用的范围,这里声明为函数
@Order(Ordered.HIGHEST_PRECEDENCE)  //声明注解的优先级为最高,假设有多个注解,先执行这个
annotation class Hanler(val handler: HandlerType)  //自定义注解类,HandlerType是一个枚举类型,里面定义的就是学生和老师的增删改操作,在这里就不展示具体内容了
复制代码
  1. 接下来就是要定义切面类了
@Aspect   //该注解声明这个类为一个切面类
@Component
class HandlerAspect{

 @Autowired
 private lateinit var handlerService: HandlerService

@AfterReturning("@annotation(handler)")   //当有函数注释了注解,将会在函数正常返回后在执行我们定义的方法
fun hanler(hanler: Hanler) {
    handlerService.add(handler.operate.value)   //这里是真正执行记录的方法
}
}
复制代码
  1. 最后就是我们本来的业务方法了
/**
* 删除学生方法
*/
@Handler(operate= Handler.STUDENT_DELETE)   //当执行到删除学生方法时,切面类就会起作用了,当学生正常删除后就会执行记录方法,我们就可以看到记录方法生成的数据
fun delete(id:String) {
   studentService.delete(id)
}
复制代码

3. AOP实现原理

我们现在了解了代码中如何实现,那么AOP实现的原理是什么呢?之前看了一个博客说到,提到AOP大家都知道他的实现原理是动态代理,显然我之前就是不知道的,哈哈,但是相信阅读文章的你们一定是知道的。

讲到动态代理就不得不说代理模式了, 代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式包含如下角色:subject:抽象主题角色,是一个接口。该接口是对象和它的代理共用的接口; RealSubject:真实主题角色,是实现抽象主题接口的类; Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象提供与真实对象相同的接口,以便代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。如下图所示:

 

 

那么代理又分为静态代理和动态代理,这里写两个小的demo,动态代理采用的就是JDK代理。举个例子就是现在一个班上的学生需要交作业,现在由班长代理交作业,那么班长就是代理,学生就是被代理的对象。

3.1 静态代理

首先,我们创建一个Person接口。这个接口

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值