文章目录

  • 1、Spring容器
    • 1.1、使用应用上下文
  • 2、装配Bean
    • 2.1、自动化装配bean
      • 2.1.1、创建可被发现的bean
      • 2.1.2、@ComponentScan注解启用组件扫描
      • 2.1.3、为组件扫描的bean命名
      • 2.1.4、设置组件扫描的基础包
      • 2.1.5、通过为bean添加注解实现自动装配
    • 2.2、通过Java代码装配bean
      • 2.2.1、创建配置类
      • 2.2.2 声明简单的bean
      • 2.2.3、借助JavaConfig实现注入
    • 2.3、通过XML装配bean
      • 2.3.1、声明一个简单的< bean>
      • 2.3.2、借助构造器注入初始化bean
  • 3、总结

1、Spring容器

在了解依赖注入(DI)详情之前,需要先了解Spring的容器。

在基于Spring的应用中,应用对象生存于Spring容器(container)中。Spring容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡(在这里,可能就是new到finalize())。

在后面,我们将了解如何配置Spring,从而让它知道该创建、配置和组装哪些对象。但首先,最重要的是了解容纳对象的容器。理解容器将有助于理解对象是如何被管理的。

Spring容器并不是只有一个。Spring自带了多个容器实现,可以归为两种不同的类型。

  • bean工厂: 由org.springframework.beans.factory.eanFactory接口定义,是最简单的容器,提供基本的DI支持。
  • 应用上下文: 由org.springframework.context.ApplicationContext接口定义,基于BeanFactory构建,并提供应用框架级别的服务,例如从属性文件解析文本信息以及发布应用事件给感兴趣的事件监听者。

这篇文章主要把精力集中在应用上下文的使用上。

1.1、使用应用上下文

Spring自带了多种类型的应用上下文。下面罗列的几个是你最有可能遇到的。

  • AnnotationConfigApplicationContext: 从一个或多个基于Java的配置类中加载Spring应用上下文。
  • AnnotationConfigWebApplicationContext: 从一个或多个基于Java的配置类中加载Spring
    Web应用上下文。
  • ClassPathXmlApplicationContext: 从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
  • FileSystemXmlapplicationcontext: 从文件系统下的一个或多个XML配置文件中加载上下文定义。
  • XmlWebApplicationContext: 从Web应用下的一个或多个XML配置文件中加载上下文定义。

例如,如下代码展示了如何加载一个FileSystemXmlApplicationContext:

ApplicationContext context = new FileSystemXmlApplicationContext("D://config.xml");

类似地,你可以使用ClassPathXmlApplicationContext从应用的类路径下加载应用上下文:

ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");

使用FileSystemXmlApplicationContext和使用ClassPathXmlApp-licationContext的区别在于:

  • FileSystemXmlApplicationContext是在指定的文件系统路径下查找knight.xml文件。
  • ClassPathXmlApplicationContext是在所有的类路径(包含JAR文件)下查找 knight.xml文件。

如果想从Java配置中加载应用上下文,那么可以使用AnnotationConfig-ApplicationContext:

AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext(JavaConfig.class);

应用上下文准备就绪之后,我们就可以调用上下文的getBean()方法从Spring容器中获取bean。

2、装配Bean

创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质。

Spring配置的三种装配机制

  • 隐式的bean发现机制和自动装配。
  • 在Java中进行显式配置。
  • 在XML中进行显式配置。

2.1、自动化装配bean

Spring从两个角度来实现自动化装配:

  • 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
  • 自动装配(autowiring):Spring自动满足bean之间的依赖。

2.1.1、创建可被发现的bean

使用@Component注解。这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean
例如:

@Component
public class Person {}

Person 的具体内容并不重要。需要注意的就是 Person 类上使用了@Component注解。

不过,组件扫描默认是不启用的 。我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。

2.1.2、@ComponentScan注解启用组件扫描

例如:

@Configuration
@ComponentScan
public class JavaConfig {}

Configuration注解表明这个类是一个配置类

JavaConfig 类使用了@ComponentScan注解,这个注解能够在Spring中启用组件扫描。

如果没有其他额外配置的话,@ComponentScan默认会扫描与配置类相同的包。假设 JavaConfig 类位于 com.springLearn 包中,因此Spring将会扫描这个包以及这个包下的所有子包,查找带有@Component注解的类。

如果 Person 类也在 com.springLearn包下,这样就能发现 Person ,并且会在Spring中自动为其创建一个bean。

如果想要使用XML来启用组件扫描的话,那么可以使用Spring context命名空间的 < context:component-scan>元素。
例如:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.springLearn"/></beans>

2.1.3、为组件扫描的bean命名

Spring应用上下文中所有的bean都会给定一个ID。Spring会根据类名为其指定一个ID。具体来讲,这个bean所给定的ID是将类名的第一个字母变为小写。 (请记住这句话,非常重要!)

如果想为这个bean设置不同的ID,所要做的就是将期望的ID作为值传递给@Component注解。
例如:

@Component("myPerson")
public class Person {}

2.1.4、设置组件扫描的基础包

到现在为止,我们没有为 @ComponentScan 设置任何属性。这意味着,按照默认规则,它会以配置类所在的包作为基础包(basepackage)来扫描组件。但是,如果想扫描不同的包,那该怎么办呢?或者,如果想扫描多个基础包,那又该怎么办呢?

要满足这样的需求其实也完全没有问题!为了指定不同的基础包,所需要做的就是在@ComponentScan的value属性中指明包的名称:
例如:

@Configuration
@ComponentScan("com.otherPackages")
public class JavaConfig {}

如果你想更加清晰地表明你所设置的是基础包,那么你可以通过basePackages属性进行配置:

@Configuration
@ComponentScan(basePackages="com.otherPackages")
public class JavaConfig {}

注意:basePackages属性使用的是复数形式。如果想要设置多个基础包,只需要将basePackages属性设置为要扫描包的一个数组即可:

@Configuration
@ComponentScan(basePackages={"com.otherPackage1", "com.otherPackage2", ......})
public class JavaConfig {}

除此之外@ComponentScan还提供了另外一种方法,那就是将其指定为包中所包含的类或接口:

@Configuration
@ComponentScan(basePackageClasses={"Person.class", "Foots.class", ......})
public class JavaConfig {}

2.1.5、通过为bean添加注解实现自动装配

自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。为了声明要进行自动装配,我们可以借助Spring的@Autowired注解。
例如:

@Component
public class Person {@Autowiredprivate Foots foots;}

这种写法等同于下面这种写法:

@Component
public class Person {private Foots foots;@Autowiredpublic Person(Foots foots) {this.foots = foots;}}

这就是@Autowired注解的构造器注入方式。

@Component
public class Person {private Foots foots;@Autowiredpublic void setFoots(Foots foots) {this.foots = foots;}}

@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上。

不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。
假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。

为了避免异常的出现,你可以将@Autowired的为了避免异常的出现,你可以将@Autowired的required属性设置为false:

@Component
public class Person {@Autowired(required = false)private Foots foots;}

将required属性设置为false时,Spring会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状态。

但是,把required属性设置为false时,需要谨慎对待。如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性有可能会出现NullPointerException。

2.2、通过Java代码装配bean

2.2.1、创建配置类

在上文中,已经用到了JavaConfig类,现在来重温一下。

@Configuration
public class JavaConfig {}

Configuration注解表明这个类是一个配置类

2.2.2 声明简单的bean

要在JavaConfig中声明bean,我们需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加@Bean注解

@Bean
public Person person(){return new Person();
}

@Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终产生bean实例的逻辑。

默认情况下,bean的ID与带有@Bean注解的方法名是一样的。在本例中,bean的名字将会是person。如果你想为其设置成一个不同的名字的话,那么可以重命名该方法,也可以通过name属性指定一个不同的名字

@Bean(name = "myPerson")
public Person person(){return new Person();
}

2.2.3、借助JavaConfig实现注入

@Bean
public Person person(Foots foots){return new Person(foots);
}

在这里,person()方法请求一个Foots作为参数。当Spring调用person()创建Person bean的时候,它会自动装配一个Foots到配置方法之中。然后,方法体就可以按照合适的方式来使用它。借助这种技术,person()方法也能够将Foots注入到Person的构造器中
前提是Person 类必须有对应的构造函数才行。

2.3、通过XML装配bean

2.3.1、声明一个简单的< bean>

要在基于XML的Spring配置中声明一个bean,我们要使用springbeans模式中的另外一个元素:< bean>。< bean>元素类似于JavaConfig中的@Bean注解。

< bean class="com.springLearn.Person"/>

因为没有明确给定ID,所以这个bean将会根据全限定类名来进行命名。
在本例中,bean的ID将会是“com.springLearn.Person#0”。其中,“#0”是一个计数的形式,用来区分相同类型的其他bean。如果你声明了另外一个Person,并且没有明确进行标识,那么它自动得到的ID将会是“com.springLearn.Person#1”。

因此,通常来讲更好的办法是借助id属性,为每个bean设置一个你自己选择的名字:

< bean id="person" class="com.springLearn.Person"/>

2.3.2、借助构造器注入初始化bean

在Spring XML配置中,只有一种声明bean的方式:使用< bean>元素并指定class属性。Spring会从这里获取必要的信息来创建bean。

构造器注入bean引用使用< constructor-arg>元素,在此之前先多声明一个Foots的Bean:

<bean id="foots" class="com.Foots"/><bean id="person" class="com.Person"><constructor-arg ref="foots"/>
</bean>

3、总结

Spring框架的核心是Spring容器。容器负责管理应用中组件的生命周期,它会创建这些组件并保证它们的依赖能够得到满足,这样的话,组件才能完成预定的任务。
在本文中,在Spring中装配bean的三种主要方式:自动化配置、基于Java的显式配置以及基于XML的显式配置。不管采用什么方式,这些技术都描述了Spring应用中的组件以及这些组件之间的关系。
我个人比较喜欢使用自动化配置,第一简单,第二是避免显式配置所带来的维护成本。但是,如果你确实需要显式配置Spring的话,应该优先选择基于Java的配置,它比基于XML的配置更加强大、类型安全并且易于重构

该文中只学习了DI的一部分,关于高级装配中的profile、条件化的Bean、Bean的作用域、运行时值的注入和SpEL这些内容会在后面的高级装配文章中涉及。


技 术 无 他, 唯 有 熟 尔。
知 其 然, 也 知 其 所 以 然。
踏 实 一 些, 不 要 着 急, 你 想 要 的 岁 月 都 会 给 你。


Spring学习总结(一)- Spring的核心特性之依赖注入(DI)总结相关推荐

  1. Spring学习(二)—— 对象创建方式及依赖注入

    文章目录 对象创建方式 配置 依赖注入 构造器注入 Set方式注入 拓展方式注入 对象创建方式 默认使用无参构造器创建 当我们需要使用有参构造器时,有以下几种方式: 1.下标赋值 <!--第一种 ...

  2. Spring学习-初识Spring

    这几天一直在看Spring.虽然已经看到了第3章,但是感觉没多大收获,所以我又回过头,再温习一下. Spring是什么? Spring是一个开源框架,最早由Rod Johnson创建,Spring是为 ...

  3. spring学习笔记(spring概述和IOC)

    spring5 1.spring的概述 1.1.spring是什么 Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,它是为了解决企业应用开发的复杂性而创建的. Spring 的 ...

  4. Spring 学习之 二----Spring创建对象的三种方式

    最近在系统的学习Spring,现在就Spring的一些知识进行总结. 我们知道Spring是一个开放源代码的设计层面的框架,他主要解决的是业务逻辑层与其他各层之间松耦合的问题. Spring 有三个核 ...

  5. Spring框架—③依赖注入DI、Bean作用域及自动装配

    依赖注入 DI,Dependency injection 依赖: 指bean对象的创建依赖于Spring容器 注入: 指Bean对象所依赖的资源,由容器来设置和装配 在beans.xml中配置 1.常 ...

  6. Spring核心——Bean的依赖注入

    依赖注入 在设计模式与IoC这篇文章中,介绍了Spring基础的三大支柱的两项内容--IoC.Bean.本篇将继续围绕着Bean的创建时的注入方式来介绍Spring的核心思想与设计模式. 天底下所有面 ...

  7. [spring学习] 1、spring下载与使用

    目录 spring介绍 spring核心部分 spring的下载 idea使用spring 总结 spring介绍 Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Jo ...

  8. Spring学习4之依赖注入(DI)

    前言 上节学习了IOC创建对象的方式,我们在不知不觉中使用了最简单的构造注入,什么是构造注入,什么又是依赖注入呢? 一.首先我们要了解DI是什么? 创建对象的过程中Spring可以依据配置对象的属性进 ...

  9. Spring学习笔记 之 Spring<全>

    开始学习Spring全家桶 文章目录 1. IoC 定义 为什么叫控制反转? 实现 IoC 容器创建 bean 的两种⽅式 IoC DI 特殊字符的处理 Spring 中的bean创建类型 -- sc ...

最新文章

  1. lstm timestep一般是多少_请问rnn和lstm中batchsize和timestep的区别是什么?
  2. 2011 ScrumGathering敏捷个人.pptx
  3. 安装包镜像_创建 macOS Catalina cdr格式镜像安装包
  4. 服务器响应回调函数,解决有关flask-socketio中服务端和客户端回调函数callback参数的问题(全网最全)...
  5. pwn环境搭建_pwndbg、pwntools环境搭建(Unix系统)
  6. 你看,公司状告员工不加班,居然还告赢了
  7. ENtEntityFranework 的简单应用(一)
  8. 【LeetCode】241. Different Ways to Add Parentheses
  9. 水晶易表 跨域不能访问数据的解决方案
  10. 【渝粤教育】国家开放大学2018年春季 0100-22T程序设计基础 参考试题
  11. mybatis 的 dao 接口跟 xml 文件里面的 sql 是如何建立关系的?
  12. 深入分析windows和Linux动态链接库的应用异同[转]
  13. java 语音传输_java – 通过tcp流式传输语音
  14. 密码学和Java加密与解密技术
  15. 无线路由器桥接 - 终极完美教程
  16. css浮动,清除浮动,溢出属性,定位,设置透明度
  17. 用Python ttkbootstrap 带你制作账户注册信息界面
  18. Onedrive如何同步文件夹
  19. 关于centos7配置网卡qqf
  20. 不能直接获取?聊聊如何在Shader Graph中获取深度图

热门文章

  1. InfoJet Service,一个InfoPath Web表单产品
  2. 全球虚拟运营商发展现状与探索
  3. 一台计算机只能注册一台sql,局域网中的一台电脑为啥连接不到另一台电脑中的SQL远程数据库...
  4. 从学会用橡皮鸭 debug 的那天,我,走上一条不归之路
  5. 线性代数:特征值、特征多项式和特征向量
  6. React-虚拟DOM
  7. atom 插件下载错误:【Fetching featured packages failed.self signed certificate in certificate chain】
  8. 个人认为最高效的学习方法【费曼学习法】
  9. linux zip unzip指令使用方法
  10. 简单航班查询系统java_基于jsp的航班信息查询-JavaEE实现航班信息查询 - java项目源码...