前言

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种类型的通知。

  1. 前置通知(Before):在目标方法被调用之前调用通知功能。
  2. 后置通知(After):在目标方法完成之后调用通知,此时不关心方法的输出是什么。
  3. 返回通知(After-returning):在目标方法成功执行之后调用通知。
  4. 异常通知(After-throwing):在目标方法抛出异常后调用。
  5. 环境通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

连接点(Join Point)

应用有很多的时机去应用(调用通知),这些时机被称为连接点。连接点是应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

切点(Poincut)

如果通知定义了切面的”什么(what)“和”何时(when)" 的话,那么切点就定义了“何出(where)"。切点的定义会匹配要织入的一个或多个连接点。通常使用明确的类和方法名称,或者是利用正则表达式来定义所匹配的类和方法名来指定切点。

切面(Aspect)

切面是通知和切点的结合,通知和切点来定义了切面的全部内容,它是什么,在何时何处完成其功能。

引入(Introduction)

引入允许向现有的类添加新方法和属性。

织入(Weaving)

织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期中有多个点可以织入。编译期(AspectJ),类加载期(AspectJ5 支持),运行期(Spring Aop 以这种方式织入切面的)。

总结一下:通知包含了需要应用多个应用对象的横切行为;连接点是程序执行过程中能够应用通知的所有点;切点定义了通知被应用的具体位置(即哪些连接点)。简而言之:切点定义了哪些连接点会得到通知。

Spring 对AOP的支持

创建切点来定义切面所织入的连接点是AOP框架的基本功能。

Spring 提供了4种AOP的支持。

  1. 基于代理的经典Spring Aop
  2. 纯POJO切面
  3. @AspectJ 注解驱动的切面
  4. 注入式AspectJ 切面(适用于Spring 各版本)

前三种都是Spring Aop 的变体,SpringAop 构建在动态代理基础之上(即基于动态代理),Spring对AOP的支持局限于方法拦截。

理解了这些概念后如何应用Spring AOP就相对而言来说简单的多了。

总结

DI目的只有一个就是解耦,实现代码的松散耦合。解决高耦合的代码带来的不易测试、不易复用的问题。

AOP解决的问题是如何把应用中横切关注点与业务逻辑相分离,解耦。把之前分散在应用各处的行为放入可重用的模块中,有效减少了代码冗余,并让类更关注于自身的主要功能和业务逻辑。

如何快速理解Spring中的DI和AOP的更多相关文章

  1. 理解Spring中的IOC和AOP

    我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式 IOC就是典型的工厂模式,通过ses ...

  2. 5分钟简述Spring中的DI与AOP

    Spring的两个核心特性: 依赖注入(dependency injection,DI) 面向切面编程(aspect oriented programming,AOP) 依赖注入(dependency ...

  3. 深入理解spring中的各种注解

    Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...

  4. 深入理解spring中的各种注解(转)

    Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...

  5. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  6. 详谈 Spring 中的 IOC 和 AOP

    这篇文章主要讲 Spring 中的几个点,Spring 中的 IOC,AOP,下一篇说说 Spring 中的事务操作,注解和 XML 配置. Spring 简介 Spring 是一个开源的轻量级的企业 ...

  7. Spring中基于xml的AOP

    1.Aop 全程是Aspect Oriented Programming 即面向切面编程,通过预编译方式和运行期动态代理实现程序功能的同一维护的一种技术.Aop是oop的延续,是软件开发中的 一个热点 ...

  8. 理解Spring中的IoC和DI

    什么是IoC和DI IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度.其基本思想是:借助于"第三方" ...

  9. 用通俗的语言解释 Spring 中的 DI 、IOC 和AOP概念

    DI 所谓依赖,从程序的角度看,就是比如A要调用B的方法,那么A就依赖于B,反正A要用到B,则A依赖于B.所谓倒置,你必须理解如果不倒置,会怎么着,因为A必须要有B,才可以调用B,如果不倒置,意思就是 ...

随机推荐

  1. 令人迷惑的Gamma

    概述 首先我想说,接触到Gamma的概念也很长时间了,一直没有认真的去学习它.知其然而不知其所以然.最近恰巧学到了这一部分,就想彻底地搞懂它. CRT 说起Gamma,肯定离不开CRT(阴极射线管). ...

  2. linux 下强大的 JSON 解析命令 jq

    介绍 jq is like sed for JSON data - you can use it to slice and filter and map and transform structure ...

  3. 官方解读:Salesforce线上考试新政与福利

    随着疫情在世界范围内的迅速蔓延,Salesforce推出了一系列的线上认证考试改进方案,方便Salesforce从业者在疫情阶段也能够安全.便利地参与考试,今天让我们一起来捋一捋那些,和我们密切相关的 ...

  4. [apue] getopt 可能重排参数

    看第21章时,介绍到了解析命令行的神器 getopt,了解了 linux 下处理通用命令行的方法. 命令行可分为参数与选项,其中不带 - 或 -- 前缀的为参数,对一个命令而言数量是固定的,多个参数之 ...

  5. 详解 HashMap

    本篇博文的知识点,在我们的日常生活中,应用十分广阔.比如:每个学生,都有自己的对应的学号.每一个公民,都有自己的身份证号- - 相信看到这里,有的同学基本上已经猜到了这个类的主要用途.那么,话不多说, ...

  6. wechall前十题

    今天开始打一打wechall 累了打wechall,不累的时候开始打buu 第一题:Get Sourced 查看源代码即可,拉到底部 第二题:Stegano 属于misc的范畴,直接下载下来,然后no ...

  7. docker环境常用命令

    Ubuntu 安装docker及docker-compose 安装: apt-get install docker apt-get install docker-compose 启动docker环境: ...

  8. Springboot:属性常量赋值以及yml配置文件语法(四)

    方式一: 注解赋值 构建javaBean:com\springboot\vo\Dog 1:@Component:注册bean到spring容器中 2:添加get set toString方法 3:使用 ...

  9. Python 实用冷门知识整理

    1.print 打印带有颜色的信息 大家知道 Python 中的信息打印函数 print,一般我们会使用它打印一些东西,作为一个简单调试. 但是你知道么,这个 Print 打印出来的字体颜色是可以设置 ...

  10. Python数据预处理:使用Dask和Numba并行化加速

    如果你善于使用Pandas变换数据.创建特征以及清洗数据等,那么你就能够轻松地使用Dask和Numba并行加速你的工作.单纯从速度上比较,Dask完胜Python,而Numba打败Dask,那么Num ...