如何快速理解Spring中的DI和AOP
前言
Spring框架通过POJO最小侵入性编程、DI、AOP、模板代码手段来简化了Java 开发,简化了企业应用的开发。POJO和模板代码相对来说好理解,本篇重点解读下DI和AOP。
一 DI
DI(依赖注入)定义
对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定。对象无需自行的创建或管理它们的依赖关系。
背景和问题
我们行来假设没有Spring 来管理注入依赖关系,我们是怎么来实现依赖关系管理的,直接在对象内部通过new进行创建对象,每个对象负责管理与自己相互协作的的对象(即它所依赖的对象)的引用,是程序主动去创建依赖对象。下面的一段代码是在没有用Spring 来实现DI的情况下,我们是怎么做的,这样做的问题在哪?
1.高度的耦合,RecognitionServiceImpl 和ContractRepository 两者耦合在一起。
2.难以测试,如果我们想测试RecognitionService,在不改代码下很难来测试。
public class RecognitionServiceImpl implements RecognitionService {
ContractRepository contractRepository = new ContractRepository();
}
解决方案
通过DI,对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定。对象无需自行的创建或管理它们的依赖关系。DI带来的最大的收益是——松耦合。其次是面向接口依赖的可替换(常用的是测试的时候使用mock实现)
在Spring 框架中怎么来实现DI呢?
在Spring中创建应用组件之间的协作方式通常称为装配(wiring)。它提供了三种装配实现方式,分别是XML装配、JavaConfig装配、自动装配。
Spring 的装配方式
XML装配(在XML中显示配置)
JavaConfig装配(基于Java的配置 )
自动化装配
Spring从两个角度实现自动化装配:
组件扫描(component scanning) : Spring会自动发现应用上下文中所创建的bean
自动装配(autowiring) : Spring自动满足bean之间的依赖。
简单来说,DI目的只有一个就是解耦,实现代码的松散耦合。高耦合的代码不易测试、不易复用。
二、AOP
AOP的定义
AOP,面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑外的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。是不是有点不太好理解。我们先有个概念上的认识,就是面向切面编程。所谓切面,横切关注点模块化为特殊的类,这些类被称为切面。
背景和问题
理解AOP最关键的点是先理解横切关注点,所谓的横切关注点是指散布于应用中的多处功能。最典型的横切关注点有日志记录、性能统计、安全控制、事务处理、异常处理、缓存等。这些横切的关注点从概念上与应用的业务逻辑相分离的(但是往往会直接嵌入到应用的业务逻辑中去)。没有AOP,我们往往会把这些横切的关注点来直接嵌入到业务逻辑中去,这样做的一个问题是什么?一是分散在多处,就是这类的代码分散在多处代码中,重复出现。二是 与业务代码耦合在一起。把这些横切关注点与业务逻辑相分离,解耦是面向切面编程(AOP)要解决的问题。
解决方案
通过AOP 来解决横切关注点与业务逻辑相分离解耦。横切关注点要以描述为影响多处的功能,例如:安全就是一个横切关注点,应用中的许多方法都会涉及到安全规则,事务也是一个横切关注点,应用在很多方法中。
横切关注点可以被模块化为特殊的类,这些类被成为切面(aspect)。切面有两个好处,一是每个关注点都集中于一个地方,二服务模块更加的简洁,只需主要关注于业务逻辑,像安全,事务等次要的关注点被转移到了切面中。
AOP术语
AOP已经有了自己的一些术语。描述切面的常用术语有通知(advice)、切点(point)、和连接点。
通知(advice)
在aop 术语中,切面的工作被成为通知。通知定义了切面是什么以及何时使用。通知有两个功能,一个是描述切面要做什么?另一个是何时做。简单来说是在某个方法被调用之前执行,还是之后执行,还是之前之后都要执行,还是只在方法抛出异常是执行。
Spring 切面可以应用5种类型的通知。
- 前置通知(Before):在目标方法被调用之前调用通知功能。
- 后置通知(After):在目标方法完成之后调用通知,此时不关心方法的输出是什么。
- 返回通知(After-returning):在目标方法成功执行之后调用通知。
- 异常通知(After-throwing):在目标方法抛出异常后调用。
- 环境通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
连接点(Join Point)
应用有很多的时机去应用(调用通知),这些时机被称为连接点。连接点是应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。
切点(Poincut)
如果通知定义了切面的”什么(what)“和”何时(when)" 的话,那么切点就定义了“何出(where)"。切点的定义会匹配要织入的一个或多个连接点。通常使用明确的类和方法名称,或者是利用正则表达式来定义所匹配的类和方法名来指定切点。
切面(Aspect)
切面是通知和切点的结合,通知和切点来定义了切面的全部内容,它是什么,在何时何处完成其功能。
引入(Introduction)
引入允许向现有的类添加新方法和属性。
织入(Weaving)
织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期中有多个点可以织入。编译期(AspectJ),类加载期(AspectJ5 支持),运行期(Spring Aop 以这种方式织入切面的)。
总结一下:通知包含了需要应用多个应用对象的横切行为;连接点是程序执行过程中能够应用通知的所有点;切点定义了通知被应用的具体位置(即哪些连接点)。简而言之:切点定义了哪些连接点会得到通知。
Spring 对AOP的支持
创建切点来定义切面所织入的连接点是AOP框架的基本功能。
Spring 提供了4种AOP的支持。
- 基于代理的经典Spring Aop
- 纯POJO切面
- @AspectJ 注解驱动的切面
- 注入式AspectJ 切面(适用于Spring 各版本)
前三种都是Spring Aop 的变体,SpringAop 构建在动态代理基础之上(即基于动态代理),Spring对AOP的支持局限于方法拦截。
理解了这些概念后如何应用Spring AOP就相对而言来说简单的多了。
总结
DI目的只有一个就是解耦,实现代码的松散耦合。解决高耦合的代码带来的不易测试、不易复用的问题。
AOP解决的问题是如何把应用中横切关注点与业务逻辑相分离,解耦。把之前分散在应用各处的行为放入可重用的模块中,有效减少了代码冗余,并让类更关注于自身的主要功能和业务逻辑。
如何快速理解Spring中的DI和AOP的更多相关文章
- 理解Spring中的IOC和AOP
我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式 IOC就是典型的工厂模式,通过ses ...
- 5分钟简述Spring中的DI与AOP
Spring的两个核心特性: 依赖注入(dependency injection,DI) 面向切面编程(aspect oriented programming,AOP) 依赖注入(dependency ...
- 深入理解spring中的各种注解
Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...
- 深入理解spring中的各种注解(转)
Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...
- 通过BeanPostProcessor理解Spring中Bean的生命周期
通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...
- 详谈 Spring 中的 IOC 和 AOP
这篇文章主要讲 Spring 中的几个点,Spring 中的 IOC,AOP,下一篇说说 Spring 中的事务操作,注解和 XML 配置. Spring 简介 Spring 是一个开源的轻量级的企业 ...
- Spring中基于xml的AOP
1.Aop 全程是Aspect Oriented Programming 即面向切面编程,通过预编译方式和运行期动态代理实现程序功能的同一维护的一种技术.Aop是oop的延续,是软件开发中的 一个热点 ...
- 理解Spring中的IoC和DI
什么是IoC和DI IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度.其基本思想是:借助于"第三方" ...
- 用通俗的语言解释 Spring 中的 DI 、IOC 和AOP概念
DI 所谓依赖,从程序的角度看,就是比如A要调用B的方法,那么A就依赖于B,反正A要用到B,则A依赖于B.所谓倒置,你必须理解如果不倒置,会怎么着,因为A必须要有B,才可以调用B,如果不倒置,意思就是 ...
随机推荐
- C++常用注意事项
new和delete:现在还没有new[][]和delete[][],所以在用这些的时候最好用循环解决,先一个指针的数组,然后再初始化,每个元素再new一下,这样就满足了多维数组的条件:比如: int ...
- day5 作业
tips:作业 作业: 0.分别画出下面两个列表在内存中是如何存放的 l1=[11,22,[333,444]] l2=[11,22,[33,{'name':'egon','age':18}]] ''' ...
- Python刷CSDN阅读数(仅供娱乐)
#!/usr/bin/env python # -*- coding: utf-8 -*- """ @File:csdn_reads.py @E-mail:3649427 ...
- deepin右键发送博客
1. 概述 deepin系统上没有像样的笔记软件.为知笔记未提供deb打包的软件,很遗憾.商店提供的软件,界面停留在上个世纪了. 这个时候如果想通过笔记来分享到博客是一件非常困难的事情. 本篇博客就是 ...
- vue2.x学习笔记(十一)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12586416.html. 表单的输入绑定 表单的输入绑定是一块很重要的内容,因为所有的业务系统都离不开基础表单的录 ...
- jquary
1 定义: jquary是快速简介的Javascrīpt框架 2 分类 : 1) .js类 源代码的未压缩的可以进行更改的jquary 2) min ...
- DeepinV20系统文件管理器右键发送至为知笔记
1. 创作背景 昨天在深度系统上做了一个打开文件管理器选择文件右键发送文本至博客园的插件. 这个插件对于我自己来说是及其方便的东西,平时的学习积累,工作经验或者生活感悟,随手记下之后,就能够轻松发送出 ...
- testNG 下载安装
testNG的安装方法: 一.在线安装 打开eclipse 选择-->help-->Install New Software选项 ,弹出下面的弹框,Work with框输入 http:// ...
- [Yii2] 快速套模板,加载JS,CSS(HTML标签<base>)
刚开始学,弄了好久,不知道怎么加载JS.CSS,以及怎么不加载YII2自带的模板!其实真的好简单! 补: 其实是我垃圾,YII2默认访问路径是WEB,所以把style文件放到web下就能加载! 首先把 ...
- golang实现并发爬虫一(单任务版本爬虫功能)
目的是写一个golang并发爬虫版本的演化过程. 那么在演化之前,当然是先跑通一下单任务版本的架构. 正如人走路之前是一定要学会爬走一般. 首先看一下单任务版本的爬虫架构,如下: 这是单任务版本爬虫的 ...