Spring实战(第四版)学习笔记——第二章 装配bean

第二章 装配 Bean

  • 任何一个成功的应用都是由多个为了实现某个业务目标而相互协作的组件构成的。
  • 这些组件必须彼此了解,并且相互协作来完成工作
  • 传统的关联关系的方法会导致很多的问题。难以单元测试、高度耦合等
  • Spring中,对象无需自己查找或创建与其所关联的其他对象。相反,容器负责把需要相互协作的对象引用赋予给各个对象
  • 创建应用对象之间协作关系的行为通常称为装配,这也是 DI 的本质
2.1 Spring 配置的可选方案
  • 作为开发人员,需要告诉Spring要创建哪些 bean 并且如何将其装配在一起
  • 3种方式
  1. 在XML中进行显示配置
  2. 在JAVA中进行显示配置
  3. 隐式的bean发现机制和自动装配
  • 每种配置技术都会有一些重叠,选择方案没有唯一个正确答案,适合开发人员和项目就可以
  • 更建议使用自动配置的机制,显示配置越少越好。
  • 作为Spring配置的开始,先看下Spring的自动化配置
2.2 自动化装配bean
  • 在便利性方面,最强大的还是Spring的自动化配置

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

    • 组件扫描(component scanning):Spring 会自动发现应用上下文所创建的bean
    • 自动装配(autowiring):Spring 自动满足bean之间的依赖
      • 两者结合可以将显示配置降低到最少
  • 为了阐述组件扫描和装配,需要创建几个bean,他们代表了一个音响系统中的组件。首先,要创建CompactDisc(就是CD),Spring会发现它并将其创建为一个 bean 。然后,会创建一个 CDPlayer 类,让 Spring 发现它,并将 CompactDiscBean 注入进来。

2.2.1 创建可被发现的bean
  • CD和CD机为我们阐述 DI 如何运行提供了一个很好的样例

  • 如果你不将CD插入(注入)到CD播放器中,就没有用

  • 首先在 Java 中建立 CD 的概念

  • public interface CompactDisc{
      void play();
    }
    
  • CompactDisc的内容不重要,重要的是要定义成一个接口

  • 下面写个实现类

  • package soundsystem;
    import org.springframework.stereotype.Component;
    
    @Component
      public class SgtPeppers implements CompactDisc {
        private String title = "Sgt. Pepper's Lonely Hearts Club Band";  
        private String artist = "The Beatles";
        public void play() {
     			 System.out.println("Playing " + title + " by " + artist);
    			}
         }
    
  • 只需要注意到 @Component 这个注解。表明该类会成为组件类,并告知 Spring 要为这个类创建 bean 。Spring会处理妥当

  • ComponentScan 注解扫描默认不开启,需要手动打开 ,开启后,Spring会扫描这个包以及包下的所有子包,查找带有 @Component 注解的类。

  • 当发现 CompactDisc 类时,会在Spring中自动创建一个bean

  • 使用XML

  • <?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"
      xmlns:c="http://www.springframework.org/schema/c"
      xmlns:p="http://www.springframework.org/schema/p"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://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="soundsystem" />
    
    </beans>
    
2.2.2 为组件扫描的 bean 命名
  • 在前面的例子中,当没有明确的为SgtPeppersbean设置ID,但是Spring会默认根据类名为其定义ID

  • 也就是将类名的第一个字母变为小写:sgtPeppers

  • 想单独设置ID,设置 @Component

  • @Component(“abcdefg”)
    public class SgtPeppers implements CompactDisc{}
    
  • 或者使用一种为 bean 命名的方式,使用Java依赖注入规范中所提供的的 @Named 注解为bean设置ID

  • @Named(“abcdef”)
    public class SgtPeppers implements CompactDisc{}
    
2.2.3 设置组件扫描的基础包
  • 当没有为 @ComponentScan 设置属性时,会按照默认规则,以配置类所在的包作为基础包来扫描组件

  • 当我们想要将配置类单独放在包中且需要被扫描时,就需要设置组件扫描了

  • 对组件扫描的几种方式

  • 在 @ComponentScan 的value属性中指明包的名称

  • @Configuration
    @ComponentScan("soundsystem")
    public class CDPlayerConfig { }
    
  • 可以添加属性

  • @Configuration
    @ComponentScan(basePackages="soundsystem")
    public class CDPlayerConfig { }
    
  • 第二个例子中,因为设置的基础包是以 String 类型展示的,会不安全,不利于重构代码,可以将其指定为包中所包含的类或接口

  • @Configuration
    @ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.clas})
    public class CDPlayerConfig { }
    
  • 在程序中,如果所有的对象都是独立的,彼此之间没有依赖,那么仅仅需要组件扫描即可。

  • 但是,很多对象必须依赖其他的对象才能完成功能。这时候,就需要一种方法能够将组件扫描得到的bean和相关的依赖装配在一起

  • 就是自动装配

2.2.4 通过为bean添加注解实现自动装配
  • 自动装配就是让 Spring 自动满足bean依赖的一种方法,在满足依赖的过程中,会在 Spring应用上下文中寻找匹配某个bean需求的其他bean

  • 为了声明要进行自动装配,可以借助 @Autowired 注解

  • package soundsystem;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    @Component
      public class CDPlayer implements MediaPlayer {
      private CompactDisc cd;
    
      @Autowired
        public CDPlayer(CompactDisc cd) {
        this.cd = cd;
        }
        
        public void play() {
    			cd.play();
    } }
    
    • @Autowired 注解,当Spring创建 CDPlayer bean 的时候,会通过这个构造器来进行实例化并且传入一个可设置给CompactDisc 类型的bean,将一个 CompactDisc注入到 CDPlayer 中

    • @Autowired 不仅可以用在构造器上,还可以用在属性的Setter方法上,比如

@Autowired
  public void setCompactDisc(CompactDisc cd){
  this.cd = cd;
  }
  • 在Spring初始化bean之后,会尽可能的去满足 bean 的依赖。本例中,依赖时通过带有 @Autowired 注解的方法进行声明的

  • 如果没有匹配的 bean ,在应用上下文创建的时候,Spring会抛出异常。

  • 为了避免异常,可以将 @Autowired 的required属性设置为 false

@Autowired(required=false)
  public CDPlayer(CompactDisc cd) {
  this.cd = cd;
  }
  • 将 required 设置为false,Spring会尝试执行自动装配,如果没有匹配的 bean ,Spring会让这个bean处于未装配的状态。

  • 但此时,需要注意,如果没有进行null检查的话,这个属性可能会出现NullPointerException

  • 如果有多个bean 都满足依赖关系,也会抛出异常。

  • @Autowired 是Spring的注解,可以使用 @Inject,满足Java依赖注入规范的注解,同时是按照 @Named 注解

2.2.5 验证自动装配
2.3 通过Java代码装配 bean
  • 因为组件扫描和自动装配不能满足所有的情况,所以需要明确配置Spring
  • 比如,想将第三方库中的组件进行装配。
  • 可以使用 Java 和 XML。(本节使用 Java)
  • 在***显示配置***时, JavaConfig 是更好的方案。更强大、类型安全并且对重构友好。
  • 但 javaConfig 是配置代码,不应该包含任何业务逻辑。同创将它放到单独的包中,使其与应用程序逻辑分离开
2.3.1 创建配置类
  • package soundsystem;
    
    import org.spingframework.context.annotation.Configuration;
    
    @Configuration
    public class CDPlayerConfig {
    }
    
  • 创建 JavaConfig 类(显示配置)的关键是添加 @Configuration 注解,@Configuration 表明这是个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节

  • 关注一下如何使用 JavaConfig 装配 CDPlayer 和 CompactDisc

2.3.2 声明简单的bean
  • 先声明一个简单的 bean ,体验 如何使用Java来产生 bean

  • @Bean
    public CompactDisc sgtPeppers() {
      return new SgtPeppers();
    }
    
  • @Bean 注解会告诉 Spring , 这个方法会返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终产生 bean 实例的逻辑

  • 默认时,bean 的 ID 与带有 @Bean 注解的方法名一样。比如本利就是 SgtPeppers。

  • 可以重命名

  • @Bean(name="lonelyHeartsClubBand")
    public CompactDisc sgtPeppers() {
      return new SgtPeppers();
    }
    
  • 不管怎么命名,bean 都是返回了一个新的 SgtPeppers 实例

2.2.3借助 JavaConfig 实现注入
  • 上一节的例子是没有依赖的,在 JavaConfig 中,要如何将有依赖的装配一起呢

  • @Bean
    public CDPlayer cdPlayer() {
      return new CDPlayer(sgtPeppers());
    }
    
  • cdPlayer()方法像 sgtPeppers()方法一样,同样适用了 @Bean 注解,表名这个方法会创建一个 bean 实例并将其注册到 Spring 应用上下文中。所创建的 Bean Id 为 cdPlayer,与方法名字相同

  • 不过有区别,因为这里调用了需要传入 CompactDisc 对象的构造器来创建CDPlayer实例

  • 因为 sgtPeppers() 方法上添加了 @Bean 注解,Spring 将会拦截所有对它的调用,并确保直接返回该方法所创建的 bean ,而不是每次都进行实际的调用

  • 比如

  • @Bean
    public CDPlayer cdPlayer() {
      return new CDPlayer(sgtPeppers());
    }
    
    @Bean
    public CDPlayer anotherCDPlayer() {
      return new CDPlayer(sgtPeppers());
    }
    
  • 因为 Spring默认的 bean 都是单例的,不会为第二个 CDPlayer 创建完全相同的 SgtPeppers实例。

  • 所以 Spring会拦截对 SgtPeppers()的调用并确保返回的是Spring所创建的 bean,也就是Spring 本身在调用 SgtPeppers()所创建的 CompactDisc Bean。

  • 因此,两个CDPlayer bean会得到相同的 SgtPeppers实例

  • @Bean
    public CDPlayer cdPlayer(CompactDisc compactDisc) {
      return new CDPlayer(compactDisc);
    }
    
  • 这个例子中,cdPlayer() 方法请求一个 CompactDisc 作为参数。当 Spring调用 cdPlayer() 创建CDPlayer bean 的时候,它会自动装配一个 CompactDisc 到配置方法中。然后方法体就可以按照合适的方法来使用它。借助这种技术,cdPlayer()方法也能狗将 CompactDisc注入到 CDPlayer的构造器中,而不用明确引用 CompactDisc 的 @Bean 方法

  • 这是最佳的选择

  • 带有 @Bean 注解的方法可以采用任何必要的 Java 功能来产生实例

2.4 通过 XML装配 bean
  • 前面讲了让Spring自动发现和装配 bean ,还讲了如何手动干预,通过 JavaConfig 显示地装配 bean 。

  • 在装配 bean 的时候,还有一种可选方案,即XML

2.4.1 创建 XML配置规范
  • 使用 XML 为 Spring 装配 bean 之前,需要创建一个新的配置规范

  • <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context" >
      
      <!-- configuration details go here />
    
    </beans>
    
2.4.2 声明一个简单的 bean
  1. 声明bean
  • <bean class="soundsystem.SgtPeppers" />
    
  • 在没有明确命名的时候,bean 的 ID 是默认全限定类名,本例中默认是“soundsystem.SgtPeppers#0”,下一个SgtPeppers是#1

  • 可以自己设置名字

  • <bean id="compactDisc" class="soundsystem.SgtPeppers" />
    
  • 在xml配置中,bean的创建更加被动,当Spring发现这个元素时,会调用SgtPeppers的默认构造器来创建bean

2.4.3 借助构造器注入初始化bean
  • 在 XML中声明DI时,会有多种方案。具体的构造器注入,则是两种
    • 元素
    • 使用 Spring3.0 所引入的 c- 命名空间
  • 两者的区别很大程度是是否冗长繁琐,但有些配置,只有能做到
  1. 构造器注入 bean 引用
  • 当为 CDPlayer 引入所依赖的 bean 时,根据 ID 即可

  • <bean id="cdPlayer" class="soundsystem.CDPlayer">
      <constructor-arg ref="compactDisc">
    </bean>
    
  • 当 Spring 遇到这个 元素时,会创建一个 CDPlayer 实例,元素会告知 Spring 要将一个ID为 CompactDisc 的 bean 引用传递到 CDPlayer 的构造器中

  1. 使用 C 空间
  • 需要在 XML 的顶部声明

  • <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:c="http://www.springframework.org/schema/c"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd" >
      
      ...
      
    </beans>
    
  • 在 c- 命名空间和漠视生命之后,就可以使用它来声明构造器参数了

  • <bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" />
    
  • 属性名以 c:开头,就是命名空间的前缀。

  • 要装配的构造器参数名

  • -ref ,这是一个命名的约定,会告诉 Spring ,正在装配的是一个 bean的引用,这个bean的名字是 compacDisc ,而且这是个引用,而不是普通的字面量

  • 使用这种方法就直接引用了构造器参数的名称,引用参数的名称看起来有些怪异,因为这需要在编译代码的时候,将调试标志(debug symbol)保存在类代码中。如果优化构建过程,将debug symbol移除,就可能无法正常执行

  • 替代的方案就是我们使用参数在整个参数列表中的位置信息

  • <bean id="cdPlayer" class="soundsystem.CDPlayer" c:_0-ref="compactDisc" />
    
  • 注意在多个的时候要变化数字,不能一样,而且不能数字开头

  1. 将字面量注入到构造器中
  • 除了注入引用,还可以注入字面量

  • 比如,先新创建个 CompactDisc 的实现

  • package soundsystem;
    
    import java.util.List;
    
    public class BlankDisc implements CompactDisc {
    
      private String title;
      private String artist;
    
      public BlankDisc(String title, String artist) {
        this.title = title;
        this.artist = artist;
      }
    
      public void play() {
        System.out.println("Playing " + title + " by " + artist);
      }
    
    }
    
  • 对于

  • <bean id="compactDisc" class="soundsystem.BlankDisc">
        <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
        <constructor-arg value="The Beatles" />
    </bean>
    
  • 对于c空间

  • <bean id="compactDisc" class="soundsystem.BlankDisc"
          c:_title="Sgt. Pepper's Lonely Hearts Club Band" 
          c:_artist="The Beatles" />
    
  • 第一个方案就是引用构造器参数的名字

  • 也可以使用参数索引装配相同的字面量值

  • <bean id="compactDisc" class="soundsystem.BlankDisc"
          c:_0="Sgt. Pepper's Lonely Hearts Club Band" 
          c:_1="The Beatles" />
    
  1. 装配集合
  • 当类中有集合属性了

  • package soundsystem;
    
    import java.util.List;
    
    public class BlankDisc implements CompactDisc {
    
      private String title;
      private String artist;
      private List<String> tracks;
    
      public BlankDisc(String title, String artist, List<String> tracks) {
        this.title = title;
        this.artist = artist;
        this.tracks = tracks;
      }
    
      public void play() {
        System.out.println("Playing " + title + " by " + artist);
        for (String track : tracks) {
          System.out.println("-Track: " + track);
        }
      }
    
    }
    
  • <?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:c="http://www.springframework.org/schema/c"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <bean id="compactDisc"
            class="soundsystem.BlankDisc"
            c:_0="Sgt. Pepper's Lonely Hearts Club Band"
            c:_1="The Beatles">
        <constructor-arg>
          <list>
            <value>Sgt. Pepper's Lonely Hearts Club Band</value>
            <value>With a Little Help from My Friends</value>
            <value>Lucy in the Sky with Diamonds</value>
            <value>Getting Better</value>
            <value>Fixing a Hole</value>
            <!-- ...other tracks omitted for brevity... -->
          </list>
        </constructor-arg>
      </bean>
    
    </beans>
    
  • 假如集合里的不是字面量而是引用呢

  • public Discography(String artist, List<CompactDisc> cds) { ... }
    
  • 这样子

  • <bean id="beatlesDiscography"
            class="soundsystem.Discography" >
      <constructor-arg>
        <list>
          <ref bean="sgtPeppers" />
          <ref bean="whiteAlbum" />
          <ref bean="hardDaysNight" />
          <ref bean="revolver" />
          ...
        </list>
      </constructor-arg>
    </bean>
    
  • set也是一样哦

  • <bean id="compactDisc" class="soundsystem.BlankDisc" >
      <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
      <constructor-arg value="The Beatles" />
      <constructor-arg>
        <set>
          <value>Sgt. Pepper's Lonely Hearts Club Band</value>
          <value>With a Little Help from My Friends</value>
          <value>Lucy in the Sky with Diamonds</value>
          <value>Getting Better</value>
          <value>Fixing a Hole</value>
          <!-- ...other tracks omitted for brevity... -->
        </set>
      </constructor-arg>
    </bean>
    
2.4.4 设置属性
  • 之前的 CDPlayer 和 BlankDisc 完全是通过构造器注入的,没有使用属性的 Setter 方法。

  • 这节讲的是如何使用 Spring XML实现属性注入

  • 当前属性注入的 CDPlayer

  • package soundsystem;
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class CDPlayer implements MediaPlayer {
      private CompactDisc cd;
    
      @Autowired
      public CDPlayer(CompactDisc cd) {
        this.cd = cd;
      }
    
      public void play() {
        cd.play();
      }
    
    }
    
  • 在选择构造器注入和属性注入时,通用的规则:对于强依赖使用构造器注入,可选性的依赖使用属性注入

  1. 方法
  • CDPlayer 除了默认构造器,没有其他的构造器

  • <bean id = "cdPlayer" class = "soundsystem.CDPlayer" ></bean>
    
  • 如果想正常测试,必须注入属性

  • <bean id="cdPlayer" class="soundsystem.CDPlayer" >
      <property name="compactDisc" ref="compactDisc" />
    </bean>
    
  • 元素为属性的 Setter 方法所提供的的功能与 元素为构造器所提供的功能是一样的。

  • 在本例中,它引用了 ID 为 compactDisc 的 bean (通过 ref 属性),并将其注入到 compactDisc属性中(通过 setCompactDisc方法)。

  1. p 空间
  • 相对于 Spring 为<constructor -arg> 提供的 c- 空间,Spring 也提供了 p- 空间,作为 元素的替代方案

  • 先声明

  • <?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:p="http://www.springframework.org/schema/p"![在这里插入图片描述](https://img-blog.csdnimg.cn/20201014084933226.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzI3MDY3,size_16,color_FFFFFF,t_70#pic_center)
    
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
      ...
    </beans>
    
  • 为 compactDisc 属性注入

  • <bean id="cdPlayer" class="soundsystem.CDPlayer" 
          p:compactDisc-ref="compactDisc" />
    
  • p 空间属性组成

  • 在这里插入图片描述

  • ref 后面的是引用,可以使用下面方法注入字面量

将字面量注入到属性
  • 当前 BlankDisc

  • package soundsystem;
    
    import java.util.List;
    
    public class BlankDisc implements CompactDisc {
    
      private String title;
      private String artist;
      private List<String> tracks;
    
      public BlankDisc(String title, String artist, List<String> tracks) {
        this.title = title;
        this.artist = artist;
        this.tracks = tracks;
      }
    
      public void play() {
        System.out.println("Playing " + title + " by " + artist);
        for (String track : tracks) {
          System.out.println("-Track: " + track);
        }
      }
    
    }
    
  • 为其注入字面量

  • <bean id="compactDisc" class="soundsystem.BlankDisc">
      <property name="title" value="Sgt. Pepper's Lonely Hearts Club Band" />
      <property name="artist" value="The Beatles">
      <property name="tracks">
        <list>
          <value>Sgt. Pepper's Lonely Hearts Club Band</value>
          <value>With a Little Help from My Friends</value>
          <value>Lucy in the Sky with Diamonds</value>
          <value>Getting Better</value>
          <value>Fixing a Hole</value>
          <!-- ...other tracks omitted for brevity... -->
        </list>
      </property>
    </bean>
    
  • 在这里,除了使用 元素的value属性来设置 title 和 artist ,我们还使用了内嵌的 元素来设置 tracks 属性,与之前通过 装配 tracks 一样

  • 或者用 p 空间,声明后使用

  • <bean id="compactDisc" class="soundsystem.BlankDisc"
          p:title="Sgt. Pepper's Lonely Hearts Club Band"
          p:artist="The Beatles" >
      <property name="tracks">
        <list>
          <value>Sgt. Pepper's Lonely Hearts Club Band</value>
          <value>With a Little Help from My Friends</value>
          <value>Lucy in the Sky with Diamonds</value>
          <value>Getting Better</value>
          <value>Fixing a Hole</value>
          <!-- ...other tracks omitted for brevity... -->
        </list>
      </property>
    </bean>
    
  • 不能用 p 空间装配集合,没有便利的方式使用p 空间来指定一个值(或 bean 引用)的列表

  • 但是可以使用 Spring util- 命名空间,(用的不多,不记载了)

2.5 导入和混合配置
  • 在Spring 中,配置方案都不是互斥的,可以将 JavaConfig 的组件扫描和自动装配或 XML配置混合在一起。
  • 在自动装配时,并不在意要装配的 bean 来自哪里
  • 不过在显式配置时,比如在 XML 配置和 JAVA 配置中该如何引用 bean 呢
  • 之前都是介绍如何组件扫描和自动装配,几个bean之间相互注入的这种关系,接下来介绍bean 之间如何互相引用
2.5.1 在JavaConfig 中引用 XML 配置
  • 假设 CDPlayerConfig 已经变得有些笨重,想要将其拆分。

  • 一种方案就是将 BlankDisc 从 CDPlayerConfig 拆分出来,定义到她自己的 CDConfig 类中

  • package soundsystem;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class CDConfig {
      
      @Bean
      public CompactDisc compactDisc() {
        return new SgtPeppers();
      }
    
    }
    
  • compactDisc()方法已经从 CDPlayerConfig 中移除掉了,我们需要有一种方式将这两个类组合在一起。

  • 一种方法就是在 CDPlayerConfig 中使用 @Import 注解导入 CDConfig

  • package soundsystem;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    
    @Configuration
    @Import(CDConfig.class)
    public class CDPlayerConfig {
    
      @Bean
      public CDPlayer cdPlayer(CompactDisc compactDisc) {
        return new CDPlayer(compactDisc);
      }
    
    }
    
  • 第二种方法,创建一个更高级的 SoundSystemConfig ,在这个类中使用 @Import 将两个类组合在一起

  • package soundsystem;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    
    @Configuration
    @Import({CDPlayerConfig.class, CDConfig.class})
    public class CDPlayerConfig {
    }
    
  • 这两种方式,都是将 CDPlayer 的配置与 BlankDisc 的配置分开了。

  • 假设希望通过 XML 来配置 BlankDisc

  • <bean id="compactDisc" class="soundsystem.BlankDisc"
      c:_0="Sgt. Pepper's Lonely Hearts Club Band"
      c:_1="The Beatles" >
      <constructor-arg>
        <list>
          <value>Sgt. Pepper's Lonely Hearts Club Band</value>
          <value>With a Little Help from My Friends</value>
          <value>Lucy in the Sky with Diamonds</value>
          <value>Getting Better</value>
          <value>Fixing a Hole</value>
          <!-- ...other tracks omitted for brevity... -->
        </list>
     </constructor-arg>
    </bean>
    
  • 如何让 Spring 同时加载它和其他基于 Java 的配置呢

  • 使用 @ImportResource 注解

  • package soundsystem;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.ImportResource;
    
    @Configuration
    @Import(CDPlayerConfig.class)
    @ImportResource("classpath:cdconfig.xml")
    public class SoundSystemConfig {
    
    }
    
  • 两个配置在 JavaConfig 中的 CDPlayer 以及配置在 XML 中的 BlankDisc ,都会被加载到 Spring容器中

  • 因为 CDPlayer 中带有 @Bean 注解的方法,接收一个 CompactDisc 作为参数,因此 BlankDisc 将会被装配进来,此时与她是通过 XML配置的没有任何关系

2.5.2 在 XML配置中引用 JavaConfig
  • 假设正在使用 Spring 基于 XML 的配置并且意识到 配置地域 ,就需要将配置文件进行拆分

  • 在 JavaConfig 配置中,已经展现了如何使用 @Import 和 @ImportResource 来拆分 JavaConfig 类

  • 在 XML 中,可以使用 元素来拆分 XML 配置

  • 假设不再将 BlankDisc 配置在 XML 之中,而是将其配置在 JavaConfig 中,CDPlayer 则继续配置在 XML 中。

  • 那么基于 XML 的配置该如何引用一个 JavaConfig 类呢?

  • 并不可以,因为 元素只能导入其他的 XML 配置文件,并没有 XML元素能够导入 JavaConfig 类

  • 但是可以通过配置 的方式

  • 一个使用 XML 描述,一个使用 JAVA描述,将它们组合在一起,或者可以创建一个更高层次的配置文件,这个文件不声明任何的bean,只是负责将更多的配置组合起来

  • 例如,可以将 CDConfig bean 从之前的 XML 文件中移除掉,而是使用第三个配置文件将这两个组合在一起

  • <?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:c="http://www.springframework.org/schema/c"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
      
      <bean class="soundsystem.CDConfig" />
      
      <import resource="cdplayer-config.xml" />
      
    </beans>
    
  • 不管使用 JavaConfig 还是使用 XML 进行装配,都可以创建一个根配置,将多个 装配类 或 XML 文件组合在一起,并在根配置中启用组件扫描

2.6 小结
  • Spring 框架的核心是Spring 容器。容器负责管理应用中组件的生命周期,他会创建这些组件并保证他们的依赖能够得到满足
  • 本章中,看到了 Spring 中装配 bean 的三种主要方式: 自动化配置,基于Java的显示配置,以及基于XML的显示配置。
  • 尽可能使用 自动化配置,以避免显式配置所带来的的维护成本。确实需要显式配置的话,优先选择 基于Java 的配置
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值