关于后端:Spring-中-Bean-的配置细节

41次阅读

共计 6071 个字符,预计需要花费 16 分钟才能阅读完成。

前言

大家好,我是 god23bin,明天持续说 Spring 的内容,对于 Spring 中 Bean 的配置的,通过上一篇文章的学习,咱们晓得了 Spring 中的依赖注入,其中有两种次要的形式,别离是 基于构造方法的 DI基于 Setter 的 DI

咱们晓得,当写完一个一般的 Java 类后,想让 Spring IoC 容器在创立类的实例对象时应用构造方法实现实例对象的依赖注入,那么就须要在配置元数据中写好类的 Bean 定义,包含各种标签的属性。

如果你是第一次看我这个系列的文章,可能不晓得什么是配置元数据,不晓得什么是依赖注入,那么请你先去看看我之前的文章,置信对你是有帮忙的~

当初咱们来说说这其中的配置细节,废话不多说,开始啦!

Bean 定义中的根本标签

property

property 标签:用于注入简略属性值,能够通过 name 属性指定属性名称,通过 value 属性指定属性值,或者通过 ref 属性指定援用其余 Bean。

<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee">
    <property name="id" value="1" />
    <property name="name" value="god23bin" />
    <property name="department" ref="department" />
</bean>

<bean id="department" class="cn.god23bin.demo.domain.entity.Department">
    <property name="id" value="1" />
    <property name="name" value="JUST DO IT" />
</bean>

constructor

constructor 标签:应用构造方法参数值进行注入。通过 value 属性指定了参数的具体值,或通过 ref 属性指定了对其余 Bean 的援用。这样,在容器创立 Bean 实例时,会应用指定的参数值调用构造方法,实现构造方法注入。

<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee">
    <constructor-arg value="1" />
    <constructor-arg value="god23bin" />
    <constructor-arg ref="department" />
</bean>

<bean id="department" class="cn.god23bin.demo.domain.entity.Department">
    <constructor-arg value="1" />
    <constructor-arg value="JUST DO IT" />
</bean>

list

list 标签:用于注入 List 汇合类型的属性值,能够通过value 子标签指定元素的值,或者通过 ref 子标签指定援用其余 Bean。

<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee">
    <property name="skills">
        <list>
            <value>Java</value>
            <value>Spring</value>
            <value>MySQL</value>
        </list>
    </property>
    <property name="departments">
        <list>
            <ref bean="department" />
        </list>
    </property>
</bean>
    
<bean id="department" class="cn.god23bin.demo.domain.entity.Department">
    <constructor-arg value="1" />
    <constructor-arg value="JUST DO IT" />
</bean>

set

set 标签:用于注入 Set 汇合类型的属性值,用法和 list 标签相似。

<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee">
  <property name="setProperty">
    <set>
      <value>Value 1</value>
      <ref bean="bean1"/>
      <ref bean="bean2"/>
    </set>
  </property>
</bean>

map

map 标签:用于注入 Map 汇合类型的属性值,能够通过 entry 子标签指定键值对,键能够通过 key 属性指定,值能够通过 value 属性指定,或者通过 ref 子标签指定援用其余 Bean。

<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee">
  <property name="mapProperty">
    <map>
      <entry key="key1" value="Value 1"/>
      <entry key="key2">
        <ref bean="bean1"/>
      </entry>
    </map>
  </property>
</bean>

props 标签:用于注入 Properties 类型的属性值,能够通过 prop 子标签指定键值对,键能够通过 key 属性指定,值能够通过 value 属性指定。

<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee">
  <property name="propsProperty">
    <props>
      <prop key="key1">Value 1</prop>
      <prop key="key2">Value 2</prop>
    </props>
  </property>
</bean>

以上是 Spring XML 配置文件中 Bean 注入的罕用标签和汇合注入的标签。

depend-on 的应用

失常状况下,举个例子:

public class A {
    private B b;
    
    // 省略 getter 和 setter
}

B 这个 Bean 被写成是 A 的属性,也就是说,A 类依赖 B 类,这种失常的依赖关系下,咱们在以 XML 为配置元数据的配置文件中,能够应用 ref 属性来指定 A 的依赖项是 B。

<bean id="a" class="cn.god23bin.demo.domain.model.A">
    <property name="b" ref="b" />
</bean>

<bean id="b" class="cn.god23bin.demo.domain.model.B"/>

这种依赖关系,是很显著的 ,一下子就能看出 A 是依赖 B 的,所以咱们能够应用 ref 属性来指定依赖项, 与此同时,这个依赖项会被注入到须要它的 Bean 中,这里就是 B 的对象被注入到 A 中作为 b 属性。

那么对于依赖关系不显著,然而又有依赖关系的时候,就能够应用 depend-on 属性。

比方有一个类 C,它是 间接依赖 D 类的,也就是说 D 没有作为 C 的属性。此时,想要实例化 C,那么须要 D 先实例化好后,能力去实例化 C。

<bean /> 标签中的 depend-on 属性就可能做到这一点,让这种依赖关系不显著的,也能保障你在应用某个 Bean 时,该 Bean 的依赖项会先实例化。

<!-- 应用 depend-on 属性指定 C 这个 Bean 是依赖于 D 的 -->
<bean id="c" class="cn.god23bin.demo.domain.model.C" depend-on="d" />

<bean id="d" class="cn.god23bin.demo.domain.model.D" />

这样,在应用 C 时,是可能保障 C 的依赖项 D 是曾经实例化好的。

如果有多个依赖项,那么能够应用无效的分隔符进行宰割(英文逗号、英文分号或者空格):

<!-- 应用 depend-on 属性指定 C 这个 Bean 是依赖于 D 的 -->
<bean id="c" class="cn.god23bin.demo.domain.model.C" depend-on="d,another" />

<bean id="d" class="cn.god23bin.demo.domain.model.D" />
<bean id="another" class="cn.god23bin.demo.model.Another" />

同理,销毁对象的时候,在销毁 C 对象之前,D 就会被先销毁。

lazy-init 的应用

<bean /> 标签中的 lazy-init 属性是用来指定某个 Bean 是否开启懒加载的。

默认状况下,Bean 定义中这个属性默认值是 false,也就是说默认的 Bean 都不是懒加载的,当 Spring IoC 容器创立后,容器就会立刻去创立并齐全配置所有的单例作用域的 Bean。

如果咱们想让某个 Bean 不在一开始就被实例化,那么就能够应用这个懒加载属性开启某个 Bean 的懒加载。懒加载的 Bean,只有在被第一次应用时,才会被实例化。

在以 XML 为配置元数据为例,间接应用 lazy-init 属性,设置该属性为 true 就 OK。

<bean id="lazyBean" class="cn.god23bin.demo.domain.model.LazyBean" lazy-init="true" />

当然,如果这个懒加载的 Bean 被其余没有懒加载的单例 Bean 给援用了,那么这个懒加载的 Bean 也会在容器创立后被容器所创立,因为容器必须确保单例 Bean 的依赖项都被实例化了。

主动注入依赖项

Spring 反对 Bean 之间依赖关系的主动注入。 它能依据 ApplicationContext 的内容帮咱们解决 Bean 之间的依赖关系,这样咱们就能够不必手动在配置元数据中指定 Bean 之间的依赖关系。

网上有很多博客把「主动注入」说成「主动拆卸」的,在我看来,这是两回事,实际上从它们的英文名来看,就是两回事。

说到主动拆卸(Auto Configuration),个别都是分割到 Spring Boot 的,因为它的特点就是开箱即用,省去大量的配置,而之所以能省去大量的配置,就得益于它的主动拆卸。而主动注入(Autowiring Collaborator)是指主动注入协作者,换句话说,指 Bean 之间的依赖项 Spring 能帮你去注入。

主动注入的长处

  • 能够大大减少咱们在配置元数据中进行指定属性或构造方法的参数
  • 能够随着对象的倒退而更新配置,比方你须要给某个类增加一个新的依赖项,那么你不须要去批改配置元数据,主动注入就帮咱们解决

以 XML 作为配置元数据的状况下,咱们能够应用 <bean /> 标签中的 autowire 属性来指定主动注入的模式。

3 种主动注入的模式

默认没有主动注入,这就是最开始学习的写法,Bean 的依赖项须要用 ref 属性来指定。

  1. byName:容器会默认依据 属性名 找到一个同名的 Bean 进行主动注入。
<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee" autowire="byName">
    <!-- 属性 -->
</bean>
  1. byType:容器会默认依据 属性的类型 找到一个同类型的 Bean 进行主动注入,如果存在多个同类型的 Bean,那么 Spring IoC 容器就不晓得注入哪一个 Bean,就会抛出异样。
<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee" autowire="byType">
    <!-- 属性 -->
</bean>
  1. constructor:相似 byType,不过它是基于构造方法参数的主动注入。
<bean id="employee" class="cn.god23bin.demo.domain.entity.Employee" autowire="constructor">
    <!-- 结构函数参数 -->
</bean>

须要留神的是,主动注入只对那些具备依赖关系的 Bean 起作用,而不是所有的 Bean。因而,在配置 Bean 的时候,须要确保被注入的属性在其余 Bean 中是存在的。

主动注入的限度和毛病

  • 在配置元数据中,应用 <property /><constructor-args /> 编写的明确的依赖关系会笼罩主动注入的,换句话说,它的优先级比主动注入的形式高。还有就是主动注入是不能注入简略的类型的,比方根本数据类型、String、Class 等类型(包含这些类型的数组也是不能主动注入的)。这里的限度是设计上的限度。
  • 主动注入是单靠 Spring 帮咱们注入的,精确度不如咱们手动去明确设置 Bean 之间的依赖关系的,某些状况下可能因为咱们的忽略会注入谬误的 Bean 导致意想不到的后果。
  • 主动注入的信息对于一些用来生成文档的工具可能是没用的。
  • 主动注入的时候找到了多个匹配上的 Bean,对于数组和汇合来说是失常的,没什么问题,然而如果要注入的 Bean 是单值属性的依赖关系,那么 Spring IoC 就不晓得该注入哪一个 Bean,就会抛出异样。这个就在下面的 byType 中说过的。

对于主动注入匹配到了多个 Bean,有以下解决方案:

  • 不必主动注入,改为明确手动注入
  • 应用 <bean /> 中的 primary 属性,设置为 true,那么在多个同类型的 Bean 定义当中,如果匹配上了,那么这个 Bean 就是次要的候选者,就会注入这个 Bean。
  • 应用基于注解的主动注入(@Autowired@Primary 等)

这几个应用注解实现主动注入的,在前面的文章中再讲。

总结

咱们总结一下,对于 Spring 中 Bean 的配置与依赖注入的重要内容。

  • Bean 的配置元数据可通过 XML 文件进行定义和配置,当然后续咱们会介绍应用 注解 Java 配置 作为配置元数据的形式。
  • 根本标签包含 propertyconstructor-arglistsetmapprops,用于注入属性值或汇合类型的属性。
  • depend-on 属性用于指定 Bean 之间的依赖关系,确保指定的 Bean 先于以后 Bean 实例化,这种依赖不是显式的依赖。
  • lazy-init 属性用于指定 Bean 是否懒加载,默认为 false,即容器启动时立刻实例化所有单例 Bean。
  • 主动注入可缩小配置元数据中的显式指定依赖项,提供 autowire 属性以设置主动注入的模式。
  • 主动注入模式包含 byNamebyTypeconstructor,通过属性名或类型进行主动匹配实现依赖注入。
  • 主动注入存在肯定的限度和毛病,需注意配置的精确性和抵触解决。
  • 对于多个匹配的主动注入,可通过手动注入、primary 属性或基于注解的主动注入来解决。

以上就是本篇所有的内容了,对屏幕前的你有帮忙的话,麻烦点点关注,点个收费的赞,给予我反对与激励,感兴趣的话能够关注我这个专栏,谢谢你们!

最初的最初

心愿各位屏幕前的 靓仔靓女们 给个三连!你轻轻地点了个赞,那将在我的心里世界削减一颗亮堂而夺目的星!

咱们下期再见!

正文完
 0