前言

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. linux常用命令整理(一)

    1.sort(排序) 典型例题:sort -t: -k3n /etc/passwd 以冒号为分隔符根据第三个域的数字大小进行排序(默认分隔符是空格) 2.uniq(去除文件中的连续重复行) 典型例题: ...

  2. SQL Server 2005 sa登录失败。已成功与服务器建立连接 但是在登录过程中发生错误。 provider 共享内存提供程序 error 0 管道的另一端上无任何进程。

    SQL Server 2005 Express版 用户 'sa' 登录失败.该用户与可信 SQL Server 连接无关联.提示错误:已成功与服务器建立连接 但是在登录过程中发生错误. provide ...

  3. 杭电1080 J - Human Gene Functions

    题目大意: 两个字符串,可以再中间任何插入空格,然后让这两个串匹配,字符与字符之间的匹配有各自的分数,求最大分数 最长公共子序列模型. dp[i][j]表示当考虑吧串1的第i个字符和串2的第j个字符时 ...

  4. C - Dr. Evil Underscores CodeForces - 1285D 二进制

    题目大意:n个数,任意整数x对这n个数取异或值,然后使最大值最小. 思路:数据范围最大为pow(2,30);所以考虑二进制的话,最多有30位.对于某一位d,然后考虑数组v中每一个元素的d为是0还是1, ...

  5. E - Travel by Car

    连接https://atcoder.jp/contests/abc143/tasks/abc143_e 题目大意: 在一个无向图中,当前的油量为L,给出q个问题,判断从a到b需要多少加几次油,路上每个 ...

  6. Java的数组索引问题

    /* 数组操作的两个常见小问题: ArrayIndexOutOfBoundsException:数组索引越界异常 原因:你访问了不存在的索引. NullPointerException:空指针异常 原 ...

  7. 异常处理方式一(try-catch-finally)

    package com.yhqtv.demo01Exception; /* * 一.异常的处理,抓抛模型 * * 过程一:“抛”:程序在正常 执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异 ...

  8. (第四篇)Linux命令初识之常用系统管理命令

    1.hostname [命令作用]用于显示和设置系统的主机名称(但是不会永久保存,重启后会恢复) [命令语法]hostname(选项)(参数) [常用选项] -a:显示主机别名(alias name) ...

  9. java关于throw Exception的一个小秘密

    目录 简介 throw小诀窍 总结 java关于throw Exception的一个小秘密 简介 之前的文章我们讲到,在stream中处理异常,需要将checked exception转换为unche ...

  10. 第十二章Linux文件系统与日志

    1.inode 包含文件的元信息(1)inode 内容:文件的字节数.拥有者的 UID.GID.文件的读写执行权限.时间戳等,但不包含文件名.文件名是储存在目录的目录项中.(2)查看文件的 inode ...