《Spring实战》笔记 Ch2 装配Bean

装配Bean

Spring配置的可选方案

三种装配Bean的方式:

  • 使用XML文件进行显式的配置
  • 使用Java代码,创建一个JavaConfig的java文件,用代码进行显式
  • 用隐式的Bean发现机制和自动装配

建议是尽可能地使用自动配置的机制。显式配置越少越好。当你必须要显式配置bean的时候(比如,有些源码不是由你来 维护的,而当你需要为这些代码配置bean的时候),我推荐使用类型 安全并且比XML更加强大的JavaConfig。最后,只有当你想要使用便 利的XML命名空间,并且在JavaConfig中没有同样的实现时,才应该使用XML。

自动化创建bean

创建可被发现的Bean

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

  • 组件扫描(component scanning)
  • 自动装配 (autowiring)

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

使用了@ComponentScan注解,这个注解能够在Spring中启 用组件扫描。
如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包。因为CDPlayerConfig类位于soundsystem包中,因此 Spring将会扫描这个包以及这个包下的所有子包,查找带有@Component注解的类

如果你更倾向于使用XML来启用组件扫描的话,那么可以使 用Spring context命名空间的<context:component-scan>元素
在这里插入图片描述
CDPlayerTest使用了Spring的SpringJUnit4ClassRunner,以便在测试开始的时候自动创建Spring的应用上下文。注解@ContextConfiguration会告诉它需要在CDPlayerConfig中加载配置。因为CDPlayerConfig类中包含了@ComponentScan,因
此最终的应用上下文中应该包含CompactDiscbean。

为组件扫描的bean命名

Spring应用上下文会给所有的bean都给定一个ID。默认的是将类名的第一个字母变为小写。
如果想为这个bean设置不同的ID,你所要做的就是将期望的ID作为值 传递给@Component注解
在这里插入图片描述

设置组件扫描的基础包

有一个原因会促使我们明确地设置基础包,那就是我们想要将配置类 放在单独的包中,使其与其他的应用代码区分开来。如果是这样的
话,那默认的基础包就不能满足要求了。
所需要做的就是在@ComponentScan的value属性中指明包的名称:
在这里插入图片描述
如果你想更加清晰地表明你所设置的是基础包,那么你可以通过 basePackages属性进行配置:
在这里插入图片描述

如果想要设置多个基础包,只需要将basePackages属性设置为要扫描包名的数组即可

@Configuration
@ComponentScan(basePackages={"soundSystem", "video"})
public class CDConfig{}

上面的基础包是以String类型表示的,这种方法是类型不安全的。如果重构代码的话,所指定的基础包可能会出现问题
为了解决上面的问题,将字符串换成类名,basePackages换成basePackageClasses。这些类所在的包将会作为组件扫描的基础包。

@Configuration
@ComponentScan(basePackageClasses={MarkerInterfaceA.class, MarkerInterfaceB.class})
public class CDConfig{}

尽管在样例中,为basePackageClasses设置的是组件类,但是 你可以考虑在包中创建一个用来进行扫描的空标记接口(marker interface)。通过标记接口的方式,你依然能够保持对重构友好的接 口引用,但是可以避免引用任何实际的应用程序代码(在稍后重构
中,这些应用代码有可能会从想要扫描的包中移除掉)。

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

自动装配就是让Spring自动满足bean依赖的一种方法,在 满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求 的其他bean。用@Autowired注解告诉Spring: 这里要进行自动装配

比方说,考虑CDPlayer类。它的构造器上添加了 @Autowired注解,这表明当Spring创建CDPlayer bean的时候,会 通过这个构造器来进行实例化并且会传入一个CompactDisc类型的bean。
在这里插入图片描述

@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方 法上
在这里插入图片描述
在Spring初始化bean之后,它会尽可能得去满足bean的依赖
在本例 中,依赖是通过带有@Autowired注解的方法进行声明的,也就是setCompactDisc()
实际上,Setter方法并没有什么特殊之处。@Autowired注解可以用 在类的任何方法上。假设CDPlayer类有一个insertDisc()方法, 那么@Autowired能够像在setCompactDisc()上那样,发挥完全相同的作用:
在这里插入图片描述
不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法 参数上所声明的依赖。假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。
如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出 一个异常。为了避免异常的出现,你可以将@Autowired的
required属性设置为false:

如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常, 表明没有明确指定要选择哪个bean进行自动装配。自动装配的歧义性后面再讨论
在这里插入图片描述
将required属性设置为false时,Spring会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状 态。但是,把required属性设置为false时,你需要谨慎对待。如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性有可能会出现NullPointerException。

通过Java代码装配Bean

尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化配置 是更为推荐的方式,但有时候自动化配置的方案行不通,因此需要明 确配置Spring。比如说,你想要将第三方库中的组件装配到你的应用 中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了。必须使用显示装配的方式。

创建配置类

创建一个类,加上@Configuration注解

声明简单的bean

  • 编写一个方法,这个方法会创建Bean实例
  • 然后给这个方法加上@Bean注解
    在这里插入图片描述
    @Bean方法会告诉Spring,这个方法会返回一个对象,而且这个对象需要被注册为Sping应用上下文中的bean
    而且,默认情况下,bean的id与创建这个对象的方法名一样。如果要改名,除了重命名方法外,还可以
@Bean(name="nbsszrx")

借助JavaConfig实现注入

在JavaConfig中装配bean的最简单方式就是引用创建bean的方法
在这里插入图片描述
看起来,CompactDisc是通过调用sgtPeppers()得到的,但情况 并非完全如此。因为sgtPeppers()方法上添加了@Bean注解, Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。

可以看到,通过调用方法来引用bean的方式有点令人困惑。其实还有 一种理解起来更为简单的方式:

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

在这里插入图片描述
Spring调用此方法的时候,会自动装配一个CompactDisc到配置方法中

通过这种方式引用其他的bean通常是最佳的选择,因为它不会要求 将CompactDisc声明到同一个配置类之中。在这里甚至没有要 求CompactDisc必须要在JavaConfig中声明,实际上它可以通过组件 扫描功能自动发现或者通过XML来进行配置。你可以将配置分散到多 个配置类、XML文件以及自动扫描和装配bean之中,只要功能完整健 全即可。不管CompactDisc是采用什么方式创建出来的,Spring都
会将其传入到配置方法中,并用来创建CDPlayer bean

通过XML装配bean

创建XML配置规范

在这里插入图片描述

声明一个简单的bean

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

通过id属性设定名字,方便后面引用
在这里插入图片描述
需要注意的事情就是你不再需要直接负责创建SgtPeppers的 实例,在基于JavaConfig的配置中,我们是需要这样做的。当Spring发 现这个<bean>元素时,它将会调用SgtPeppers的默认构造器来创建bean。

借助构造器注入初始化bean

在XML中声明DI时,会有多种可选的配置方案和风格。具体到 构造器注入,有两种基本的配置方案可供选择:

  • <constructor-arg>元素
  • 使用Spring 3.0所引入的c-命名空间
    两者的区别在很大程度就是是否冗长烦琐。可以看到,<constructor-arg>元素比使用c-命名空间会更加冗长,从而 导致XML更加难以读懂。另外,有些事情<constructor-arg>可以做到,但是使用c-命名空间却无法实现。

在这里插入图片描述
当Spring遇到这个元素时,它会创建一个CDPlayer实 例。元素会告知Spring要将一个ID
为compactDisc的bean引用传递到CDPlayer的构造器中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为在XML中不允许数字作 为属性的第一个字符,因此必须要添加一个下画线作为前缀。
只有一个构造器 参数,所以我们还有另外一个方案——根本不用去标示参数:
在这里插入图片描述

注入字面量
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
有一种情况是能够 实现,c-命名空间却无法做到的

在这里插入图片描述
在这里插入图片描述
元素所做的事情与你的期望是一样的:将null传递给构造器
在这里插入图片描述
在这里插入图片描述
进行属性注入
在这里插入图片描述
<property>元素为属性的Setter方法所提供的功能

Spring为<constructor-arg>元素提供了c-命名空 间作为替代方案,与之类似,Spring提供了更加简洁的p-命名空间,作为<property>元素的替代方案

使用之前要声明p命名空间
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

导入和混合配置

可以在@Configuration注解对应的类中,使用@Import注解

@Confiuration
@Import({CDPlayerConfig.class, CDConfig.class})
public class SoundSystemConfig{
}

在JavaConfig中引用XML配置

可以在@Configuration注解对应的类中,使用@ImportResource注解

在XML配置中引用JavaConfig

元素只能导入其他的XML配 置文件,并没有XML元素能够导入JavaConfig类。
但是,有一个你已经熟知的元素能够用来将Java配置导入到XML配置 中:元素。

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值