美文网首页全栈工程师修炼指南
剑走偏锋:面向切面编程

剑走偏锋:面向切面编程

作者: 码农架构 | 来源:发表于2020-11-12 17:11 被阅读0次

    “给我一把锤子,满世界都是钉子”

    我记得曾经有这样一个相当流行的观点,是说,编程语言只需要学习一门就够了,学那么多也没有用,因为技术是一通百通的,别的编程语言可以说是大同小异。我相信至今抱有这种观点的程序员也不在少数。

    可惜,事实远没有那么美好。这个观点主要有两处值得商榷:

    • 其一,不同的技术,在一定程度上确实是相通的,可是,技术之间的关联性,远不是“一通百通”这四个简简单单的字能够解释的。妄想仅仅凭借精通一门编程语言,就能够自动打通其它所有编程语言的任督二脉,这是不现实的。
    • 其二,通常来说,说编程语言大同小异其实是很不客观的。编程语言经过了长时间的发展演化,如今已经发展出非常多的类型,用作编程语言分类标准之一的编程范型也可谓是百花齐放。

    因此我们要学习多种编程语言,特别是那些能带来新的思维模式的编程语言。现在,把这个观点泛化到普遍的软件技术上,也一样适用。我们都知道要“一切从实际出发”,都知道要“具体问题具体分析”,可是,在眼界还不够开阔的时候,特别是职业生涯的早期,程序员在武器库里的武器还非常有限的时候,依然无法避免“给我一把锤子,满世界都是钉子”,在技术选择的时候眼光相对局限。

    AOP 的概念

    面向切面编程是一种通过横切关注点(Cross-cutting Concerns)分离来增强代码模块性的方法,它能够在不修改业务主体代码的情况下,对它添加额外的行为。

    • 首先需要明确的是,AOP 的目标是增强代码模块性,也就是说,本质上它是一种“解耦”的方法,在这方面它和我们之前介绍的分层等方法是类似的,可是,它分离代码的角度与我们传统、自然的模块设计思路截然不同。
    image.png

    藉由 AOP 则可以有效地解决这些问题,对于图中横向的业务流程,我们能够保持它们独立不变,而把鉴权、事务这样的公共功能,彻底拿出去,放到单独的地方,这样整个业务流程就变得纯粹和干净,没有任何代码残留的痕迹.

    Spring 中的应用

    实现原理

    • 编译期间的静态织入,又称为编译时增强
    • 运行期间的动态代理,又称为运行时增强

    控制反转 IoC

    控制反转,IoC,即 Inversion of Control,言下之意,指的是把原有的控制方向掉转过来了。在我们常规的程序流程中,对象是由主程序流程创建的,例如,在业务流程中使用 new 关键字来创建依赖对象。

    但是,当我们使用 Spring 框架的时候,Spring 把对象创建的工作接管过来,它作为对象容器,来负责对象的查找、匹配、创建、装配,依赖管理,等等。而主程序流程,则不用关心对象是怎么来的,只需要使用对象就可以了。我们还是拿 BookService 举例子:

    public class BookService {
        @Autowired
        private BookDao bookDao;
        @Autowired
        private LoanDao loanDao;
        public Book lendOut(String bookId, String userId, Date date) {
            bookDao.update( ... );
            loanDao.insert( ... );
        }
    }
    

    读到这里,你可能会回想起前文 AOP 的内容,和 IoC 似乎有一个共同的特点:都是为了尽可能保证主流程的纯粹和简洁,而将这些不影响主流程的逻辑拿出去,只不过这两种技术,“拿出去”的是不同的逻辑。值得注意的是,对象之间的依赖关系,各层之间的依赖关系,并没有因为 IoC 而发生任何的改变。

    IoC 在实现上包含两种方式,一种叫做依赖查找(DL,Dependency Lookup),另一种叫做依赖注入(DI,Dependency Injection)

    IoC 到底能带来什么好处呢?

    • 资源统一配置管理。这个方面很好,但并不是 IoC 最大的优势,因为,如果你不把资源交给容器管理,而是自己建立一个资源管理类来管理某项资源,一样可以得到“统一管理”的所有优势。
    • 业务代码不再包含依赖资源的访问逻辑,因此资源访问和业务流程的代码解耦开了。我觉得这里的“解耦”才是 IoC 最核心的优势,它让各层之间的依赖关系变得松散。就如同上面的代码例子一样,如果哪一天我想把它依赖的 bookDao 和 loanDao 替换掉(比如,我想为 Service 层做测试),Service 一行代码都不用改,它压根都不需要知道。

    扩展阅读

    • Spring 官方文档中关于 AOP 的教程,如果你希望看到中文版,那么互联网上有不少对于这部分的翻译,只不过对应的 Spring 版本不同,内容大致是一样的,比如这一篇
    • Comparing Spring AOP and AspectJ,这是一篇关于静态织入和动态代理这两种 AOP 方式比较的文章。
    • 对于 AspectJ,如果想一瞥其扩展的语法语义,维基百科的词条就足矣;如果想了解某些细节,请参阅官方文档
    公众号:码农架构

    相关文章

      网友评论

        本文标题:剑走偏锋:面向切面编程

        本文链接:https://www.haomeiwen.com/subject/nbdlbktx.html