AOP 从静态代理到动态代理 Emit 实现

前言

AOP 为 Aspect Oriented Programming 的缩写,意思是面向切面编程。

何为切面?

一个和业务设计没有任何耦合相关的代码段,诸如:调用日志、发送邮件、甚至路由分发,一切能为代码所有且能和代码充分解耦的代码都可以作为一个业务代码的切面。

我们为什么要 AOP

我们从一个场景举例说起:

如果想要采集用户行为信息,我们需要掌握用户调用的每一个接口。这时候我们该怎么做?

如果不采用 AOP 技术,也是最简单的,所有方法体第一句话先调用日志接口将方法信息传递记录。

有何问题

实现业务没有任何问题,但随之而来的是代码臃肿不堪,难以维护等诸多问题。

如果我们采用 AOP 技术,只需要在系统启动时,将所有要采集日志的类注入,每一次调用时,AOP 框架自动调用我们的日志代码。

是不是省去很多重复无用的劳动?代码也将变得简单容易维护(如果有朝一日不需要时,只需将日志代码注释掉)。

实现思路

AOP 框架一般有静态代理和动态代理两种实现方式。

AOP 两种实现方式

何为静态代码?

静态代理,又叫编译时代码,就是在编译时,已经存在代理类,运行时直接调用方法。说得通俗一点,就是手工写代码实现代理类的方式。

我们既然要将 Log 当作一个切面,我们肯定不能去动原有的业务代码,那样也违背了面对对象设计的开闭原则。

那么要怎么做呢?我们定义一个新类BusinessProxy去包装一下这个类,为了便于在多个方法的时候区分和辨别,方法也叫Test()

image

这样,我们如果要在所有的 Business 类添加 Log,我们就在BusinessProxy添加对应的方法去封装。既不破坏原有逻辑,又可以实现前后的日志功能。

当然,我们可以有更优雅的实现方式:

我们可以定义代理类,继承自业务类。将业务类中的方法定义为虚方法,那么我们就可以重写父类的方法并且在加入日志以后再调用父类的原方法。

当然,我们可以有更优雅的实现方式:

image

我们可以使用反射的技术,写一个通用的Invode("Test"),所有的方法都可以通过该方法调用。

我们这样便实现了一个静态代理。

那我们既然有了静态代理,又为何需要动态代理?

实现过程

系统测试

总结

你可能感兴趣的:(AOP 从静态代理到动态代理 Emit 实现)