据说,80%的人没有真正理解了Spring的依赖注入(中)

简介: 据说,80%的人没有真正理解了Spring的依赖注入(中)

经过我们改造,我们现在的依赖关系树变为下面的样子


image.png


2.2 依赖注入框架


随着我们不断引入更多的依赖关系,这种复杂性将继续增长。为了解决这个复杂问题,我们需要基于依赖关系树抽取对象的创建过程。这就是依赖注入框架


一般来说,我们可以把这个过程分为三个部分:


  1. 声明需要创建的对象需要哪些依赖对象


  1. 注册创建这些依赖对象所需要的类


  1. 提供一种使用1和2两点思想创建对象的机制


通过反射,我们可以查看 Car 类的构造函数,并且知道它需要一个 Engine 参数。因此为了创建Car对象,我们必须创建至少一个Engine接口的实现类用作依赖项来使用。在这里,我们创建一个CombustionEngine 对象(为了方便,暂时当做只有一个实现类,bean冲突问题待会再说)来声明它作为依赖项来使用,就满足Car对象创建时的需求.

其实,这个过程是递归的,因为CombustionEngine 依赖于其他对象,我们需要不断重复第一个过程,直到把所有依赖对象声明完毕,然后注册创建这些依赖对象所需要的类。


第三点其实就是将前面两点思想付诸实施,从而形成一种创建对象的机制


举个例子:比如我们需要一个Car对象,我们必须遍历依赖关系树并检查是否存在至少一个符合条件的类来满足所有依赖关系。例如,声明CombustionEngine类可满足Engine节点要求。如果存在这种依赖关系,我们将实例化该依赖关系,然后移至下一个节点。

如果有一个以上的类满足所需的依赖关系,那么我们必须显式声明应该选择哪一种依赖关系。稍后我们将讨论 Spring 是如何做到这一点的。


一旦我们确定所有的依赖关系都准备好了,我们就可以从终端节点开始创建依赖对象。对于 Car 对象,我们首先实例化 CamshaftCrankshaftーー因为这些对象没有依赖关系ーー然后将这些对象传递给 CombustionEngine 构造函数,以实例化 CombunstionEngine 对象。最后,我们将 CombunstionEngine 对象传递给 Car 构造函数,以实例化所需的 Car 对象。


了解了 DI 的基本原理之后,我们现在可以继续讨论 Spring 如何执行 DI


2.3 Spring的依赖注入


Spring的核心是一个DI框架,它可以将DI配置转换为Java应用程序。


在这里我们要阐述一个问题:那就是库和框架的区别。库只是类定义的集合。背后的原因仅仅是代码重用,即获取其他开发人员已经编写的代码。这些类和方法通常在域特定区域中定义特定操作。例如,有一些数学库可让开发人员仅调用函数而无需重做算法工作原理的实现。


框架通常被认为是一个骨架,我们在其中插入代码以创建应用程序。许多框架保留了特定于应用程序的部分,并要求我们开发人员提供适合框架的代码。在实践中,这意味着编写接口的实现,然后在框架中注册实现。


image.png


2.4 ApplicationContext


Spring 中,框架围绕 ApplicationContext 接口实现上一节中概述的三个 DI 职责。通常这个接口代表了一个上下文。因此,我们通过基于 java 或基于 xml 的配置向 ApplicationContext 注册合适的类,并从 ApplicationContext 请求创建 bean 对象。然后 ApplicationContext 构建一个依赖关系树并遍历它以创建所需的 bean对象


image.png


Applicationcontext 中包含的逻辑通常被称为 Spring 容器。通常,一个 Spring 应用程序可以有多个 ApplicationContext,每个 ApplicationContext 可以有单独的配置。例如,一个 ApplicationContext 可能被配置为使用

CombustionEngine 作为其引擎实现,而另一个容器可能被配置为使用 ElectricEngine 作为其实现。


在本文中,我们将重点讨论每个应用程序的单个 ApplicationContext,但是下面描述的概念即使在一个应用程序有多个 ApplicationContext 实例时也适用。


三 基于 java 的配置


Spring为我们提供了两种基于 java 的配置方式


  1. 基本配置


  1. 自动配置


3.1 基于 java 的基本配置


基于java的基本配置的核心,其实是下面两个注解:


  1. @Configuration: 定义配置类


  1. @Bean: 创建一个bean


例如,给出我们之前定义的 Car, CombustionEngine, Camshaft, 和Crankshaft 类,我们可以创建一个下面 的配置类:


/**
 * @author milogenius
 * @date 2020/5/17 20:52
 */
@Configuration
public class AnnotationConfig {
    @Bean
    public Car car(Engine engine) {
        return new Car(engine);
    }
    @Bean
    public Engine engine(Camshaft camshaft, Crankshaft crankshaft) {
        return new CombustionEngine(camshaft, crankshaft);
    }
    @Bean
    public Camshaft camshaft() {
        return new Camshaft();
    }
    @Bean
    public Crankshaft crankshaft() {
        return new Crankshaft();
    }
}


接下来,我们创建一个 ApplicationContext 对象,从 ApplicationContext 对象获取一个 Car 对象,然后在创建的 Car 对象上调用 start 方法:


ApplicationContext context = 
    new AnnotationConfigApplicationContext(AnnotationConfig.class);
Car car = context.getBean(Car.class);
car.start();


执行结果如下:


Started combustion engine


虽然@Configuration@Bean 注解的组合为 Spring 提供了足够的信息来执行依赖注入,但我们仍然需要手动手动定义每个将被注入的 bean,并显式地声明它们的依赖关系。为了减少配置 DI 框架所需的开销,Spring 提供了基于java的自动配置。


3.2 基于 java 的自动配置


为了支持基于 java 的自动配置,Spring 提供了额外的注解。虽然我们平时可能加过很多这种类型的注解,但是有三个最基本的注解:


  1. @Component: 注册为由 Spring 管理的类
  2. @Autowired: 指示 Spring 注入一个依赖对象
  3. @ComponentScan: 指示Spring在何处查找带有@Component注解的类


3.2.1 构造函数注入


@Autowired注解用来指导 Spring ,我们打算在使用注解的位置注入一个依赖对象。例如,在 Car 构造函数中,我们期望注入一个 Engine 对象,因此,我们给 Car 构造函数添加@Autowired注解。通过使用@Component@Autowired注解改造我们Car类,如下所示:


@Component
public class Car {
  private Engine engine;
  @Autowired
  public Car(Engine engine) {
      this.engine = engine;
  }
  public void start() {
      engine.turnOn();
  }
}


相关文章
|
5月前
|
XML Java 测试技术
Spring Boot中的依赖注入和控制反转
Spring Boot中的依赖注入和控制反转
|
4月前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
53 0
|
4月前
|
设计模式 自然语言处理 Java
简单了解下Spring中的各种Aware接口实现依赖注入
在Spring框架中,Aware接口是一组用于提供特定资源或环境信息的回调接口。这些接口被设计用来允许Bean获取对Spring容器或其他相关资源的引用,并在需要时进行适当的处理。
38 2
|
4月前
|
自然语言处理 Java 开发者
简单了解下Spring中的各种Aware接口实现依赖注入
【8月更文挑战第21天】在Spring框架中,Aware接口系列是一种特殊的机制,它允许Bean在初始化过程中获取到Spring容器或容器中的特定资源,从而实现了更加灵活和强大的依赖注入方式。本文将围绕Spring中的各种Aware接口,详细探讨它们如何帮助开发者在工作和学习中更好地实现依赖注入。
111 0
|
5月前
|
缓存 Java Spring
Spring循环依赖问题之Spring不支持构造器内的强依赖注入如何解决
Spring循环依赖问题之Spring不支持构造器内的强依赖注入如何解决
|
6月前
|
设计模式 Java 测试技术
Spring Boot中的依赖注入详解
Spring Boot中的依赖注入详解
|
6月前
|
Java Spring 容器
spring如何进行依赖注入,通过set方法把Dao注入到serves
spring如何进行依赖注入,通过set方法把Dao注入到serves
|
5月前
|
XML Java 数据格式
深入理解Spring中的依赖注入原理
深入理解Spring中的依赖注入原理
|
5月前
|
Java Spring 容器
深入理解Spring Boot中的容器与依赖注入
深入理解Spring Boot中的容器与依赖注入
|
6月前
|
XML Java 数据格式
使用 Spring 实现控制反转和依赖注入
自动装配允许Spring容器通过检查已定义的bean来自动解决协作bean之间的依赖关系。 使用XML配置有四种自动装配bean的模式: • no:默认值 - 这意味着不使用自动装配,我们必须显式地命名依赖项。 • byName:按属性名称进行自动装配,因此Spring将查找与需要设置的属性同名的bean。 • byType:类似于按名称进行自动装配,仅基于属性的类型。这意味着Spring将查找具有相同类型的属性来设置的bean。如果有多个bean具有该类型,则框架会抛出异常。 • constructor:基于构造函数参数进行自动装配,意味着Spring将查找具有与构造函数参数相同类型的bea
下一篇
无影云桌面