《 Spring in action》复习笔记 - 第二章 装配 Bean

版权声明:本文为博主原创作品,如需转载请标明出处。 https://blog.csdn.net/weixin_42162441/article/details/82659306

本章内容

  • 声明 bean
  • 构造器注入和 Setter 方法注入
  • 装配 bean
  • 控制 bean 的创建和销毁

Spring 配置的可选方案

 当描述 bean 如何进行装配时, Spring 具有非常大的灵活性,它提供了三种主要的装配机制:

  • 在 XML 中进行显示配置。
  • 在 Java中进行显示配置。
  • 隐式的 bean 发现机制和自动装配。
    Tips: 根据需要使用一种,或搭配使用。
       当必须要显示配置 bean 的时候推荐使用类型安全的 JavaConfig。
       当想要使用便利的 XML 命名空间,并且在 JavaConfig 没有同样实现时,使用 XML。

自动化装配 bean

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

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

@Component 注解表明该类会作为组件类,并告知 Spring 要为这个类创建 bean 。
但是 Spring 默认不启用组件扫描,所以需要我们显示的配置

Java 类的方法

示例:

@Configuration
@ComponentScan
public class CDPlayerConfig{
}

类 CDPlayerConfig 通过 Java 代码定义了 Spring 的装配股则。如果没有其他配置, @ComponentScan 默认会扫描与配置类相同的包以及这个包下的所有子包,查找带有 @Component 注解的类,并为其创建一个 bean 。

XML 的方式

使用 XML 启用组件扫描,可以使用 Spring context 命名空间的 元素。

<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

<context:component-scan base-package=""></context:component-scan>
</beans>


为组件扫描的 bean 命名

Spring 应用上下文中所有的 bean 都会给定一个 ID 。对于没有明确配置 ID 的 bean , Spring 会根据类名为其指定。规则为——将类名的第一个字母变为小写

如何给指定的 ID

我们所要做的就是将期望的 ID 作为值传递给 @Component 注解。
示例:

@Component("lonelyHeartsClub")
public class SgtPeppers {
}

设置组件扫描的基础包

对于之前的 @ComponentScan 我们没有设置任何属性。这意味着,按照默认规则,它会以配置类所在的包作为基础包( base package )来扫描左键。但是,当我们想要把配置类放在单独的包中,使其与其他的应用代码区分开来,我们应该怎么做?

要满足这样的需求,需要做的就是在 @ComponentScan 的 value 属性中指明包的名称:

@Configuration
@ComponentScan("soundsystem")
public class CDPlayerConfig{
}

也可以明确的表明设置的是基础包,可以通过 basePackages 属性进行配置:

@Configuration
@ComponentScan(basePackages="soundsystem")
public class CDPlayerConfig{
}

如果想设置多个基础包,只需将 basePackages 属性设置为一个数组即可:

@Configuration
@ComponentScan(basePackages={"soundsystem", "video"})
public class CDPlayerConfig{
}

因为所设置的基础包是以 String 类型表示的,是可行的,但这种方法是类型不安全( not type-safe )的。当重构代码可能会出现错误。

@ComponentScan 还提供了另一种方法,那就是将其指定为包中所含的类或借口。

@Configuration
@ComponentScan(basePackageClasses={CDplayer.class, DVDPlayer.class}
public class CDPalyerConfig{
}

Tips: 可以考虑在包中创建一个用来进行扫描的空标记借口( marker interface )。

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

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

@Component
public class CDPlayer{
    private CompactDisc cd;

    @Autowired
    public CDPlayer(CompactDisc cd){
        this.cd = cd ;
    }
}

@Autowired 注解不仅能够用在构造器上,还能用在属性的 Setter 方法上。实际上,@Autowired注解可以用在类的任何方法上。发挥完全相同的作用:

@Autowired
public void insertDisc(CompactDisc cd){
this.cd = cd;
}

不管是什么方法, Spring 都会尝试满足方法参数上所声明的依赖。假如有且只有一个 bean 匹配依赖需求,则装配这个 bean 。
另外,如若将 required 属性设置为 false 时,没有匹配的 bean 会处于未装配的状态,不进行 null 检查的话,可能会出现 NullPointerException 。

通过 Java 代码装配 bean

当想要使用第三方库中的组件装配到你的应用中,没有办法添加 @Component 和 @Autowired 注解,必须要采用显示装配的方式。
JavaConfig 在概念上,它与应用程序中的业务逻辑和领域代码不同,不应该包含任何业务逻辑,也不应该侵入到业务逻辑代码中,通常会将 JavaConfig 放到单独的包中,与其他应用程序逻辑分离开来。

Java 的方式

@Configuration
public class CDPlayerConfig{
}

@Configuration 注解表明这个类是一个配置类,该类包含在 Spring 应用上下文中如何创建 bean 的细节。
可以同时使用组件扫描和显示配置。

声明简单的 bean

@Bean(name="lonelyHeartsClubBand")
public CompactDisc sgtPeppers(){
    return new SgtPeppers();
}

@Bean 注解告诉 Spring 这个方法会返回一个对象,并要注册为 Spring 应用上下文中的 bean 。默认情况下,bean 的 ID 与注解的方法名是一样的,也可通过 name 属性来设置。

借助 JavaConfig 实现注入

@Bean
public CDPlayer cdPalyer(){
    return new CDPlayer(sgtPeppers());
}
public CDPlayer cdPlayer(){
    return new CDPlayer(sgtPeppers());
}

使用带参构造器构建实例,而且因为 sgtPeppers() 添加了注解,Spring 拦截所有对它的调用,并确保直接返回该方法所创建的 bean ,而不是每次都对其进行实际的调用 。默认情况下,bean 都是单例的,所以两个 CDplayer bean 会得到相同的 sgtPeppers 实例。

另一种易于理解的方式:

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
    return new CDPlayer(compactDisc);
}

当 Spring 调用 cdPlayer() 创建 CDPlayer bean 的时候,它会自动装配一个 CompactDisc 到配置方法中。然后,方法体按照合适的方法来使用它。
通过这种方式是最佳选择,不用要求声明到同一个配置类中。甚至可以是通过组件扫描自动发现或者通过 XML 来进行配置。

以上都是使用构造器实现的 DI 功能,但是我们完全可以采用其他的 DI 配置。

@Bean
public CDPlayer cdPlayer(Disc disc) {
    CDPlayer cdPlayer = new CDPlayer();
    cdPlayer.setDics(disc);
    return cdPlayer;
}

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

创建 XML 配置规范

借助构造器注入初始化 bean

  • constructor-arg 元素
  • 使用 Spring 3.0 所引入的c - 命名空间
<bean id="cdPlayer" class="soundsystem.CDplayer">
    <constructor-arg ref="compactDisc" />
</bean>

替代方案:

<bean id="cdPalyer" class="soundsystem.CDplayer"
    c:cd-ref="compactDisc" />

以上使用了构造器参数的名称。在优化构建过程,将调试标志移除掉,这种方式可能无法正常执行。

使用位置信息的方案:

<bean id="cdPalyer" class="soundsystem.CDplayer"
    c:_0-ref="compactDisc" />

参数名称换成了参数索引,因为 XML 不允许数字作为属性的第一个字符,因此必须添加一个下划线作为前缀。
当只有一个构造器的时候,可以不用去标示参数:

<bean id="cdPalyer" class="soundsystem.CDplayer"
    c:_-ref="compactDisc" />


将字面量注入到构造器中:

<bean id="compactDisc" class="soundsystem.BlankDisc">
    <constructor-arg value="Sgt.Peppers" />
    <constructor-arg value="The Beatles:" />
</bean>
<bean id="compactDisc2" 
    class="soundsystem.BlankDisc"
    c:_0="Sgt.Peppers"
    c:_1="The Beatles:" />

装配集合:

<bean id="compactDisc" class="soundsystem.BlankDisc">
    <constructor-arg>
        <list>
            <value>Sgt.Peppers</value>
            <value>lucy in the sky</value>
        </list>
    </constructor-arg>
</bean>

设置属性

强依赖选择构造器注入,可选性依赖使用属性注入。

<bean id="cdPalyer"
    class="soundsystem.CDPlyaer">
    <property name="compactDisc" ref="compactDisc" />
    <property name="cdname" value="cdname" />
    <property name="tracks">
        <list>
            <value>Sgt.Peppers</value>
            <value>With a Little</value>
        </list>
    </property>
</bean>

相应的可以使用 p- 命名空间

<bean id="cdPlayer"
    class="soundsystem.CDPlayer"
    p:compactDisc-ref="compactDisc"
    p:cdname="cdname" />

另外也可以借助 util- 命名空来所提供的 util:list 元素,来创建一个列表的 bean 。将其声明到单独的 bean 之中。

<util:list id="trackList">
    <value>Sgt.Peppers</value>
    <value>With a Little Help from </value>
    <value>Fixing a Hole</value>
</util:list>


导入和混合配置

在 JavaConfig 中组合

两个配置类使用 @Import 组合

//在其中之一引入另一个
@Configuration
@Import(CDConfig.class)
public class CDPlayerConfig{
//......
}
//创建一个更高级别的类
@Configuration
@import({CDPlayer.class, CDConfig.class})
public class SoundSystemConfg{
}

配置类和 XML 组合

使用 @ImportResource(“path”)

@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig{
}

在 XML 配置中组合

在 XML 配置文件中导入 Java 配置

<bean class="soundsystem.CDConfig" />

在 XML 中导入 XML

<import resource="conf.xml" />

猜你喜欢

转载自blog.csdn.net/weixin_42162441/article/details/82659306