spring装配bean
1. Spring配置的可选方案
- 在XML中进行显式配置。
- 在Java中进行显式配置。
- 隐式的bean发现机制和自动装配
Spring的配置风格 是可以互相搭配的,所以你可以选择使用XML装配一些bean,使用Spring基于Java的配置(JavaConfig)来装配另一些bean,而将剩余的 bean让Spring去自动发现
2. 自动化装配bean
Spring从两个角度来实现自动化装配:
- 组件扫描(componentscanning):Spring会自动发现应用上下文中所创建的bean。
- 自动装配(autowiring):Spring自动满足bean之间的依赖。
组件扫描和自动装配组合在一起就能发挥出强大的威力,它们能够将你的显式配置降低到最少。
2.1 创建可以被发现的bean
1.编写接口以及实现类
不过,组件扫描默认是不启用的。我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean
2.开启组件扫描
备注:如果你更倾向于使用XML来启用组件扫描的话,那么可以使用Spring context命名空间的context:component-scan元素。
3.测试组件扫描
为了测试组件扫描的功能,我们创建一个简单的JUnit测试,它会 创建Spring上下文,并判断CompactDisc是不是真的创建出来了
CDPlayerTest使用了Spring的SpringJUnit4ClassRunner,以便在测试开始的时候自动创建Spring的应用上下文。注 解@ContextConfiguration会告诉它需要在CDPlayerConfig中加载配置。因为CDPlayerConfig类中包含了@ComponentScan, 因此最终的应用上下文中应该包含CompactDiscbean
2.2 为组件扫描的bean命名
- 如果不指定bean的id,默认情况下spring会以类名首字母小写作为此bean的id
- 如果想为这个bean设置不同的ID,你所要做的就是将期望的ID作为值传递给@Component注解。
- 还有另外一种为bean命名的方式,这种方式不使用@Component注解,而是使用Java依赖注入规范(Java Dependency Injection)中所提供 的@Named注解来为bean设置ID:
备注:Spring支持将@Named作为@Component注解的替代方案。两者之间有一些细微的差异,但是在大多数场景中,它们是可以互相替换的。
2.3 设置组件扫描的基础包
- 如果未为@ComponentScan设置任何属性。则按照默认规则,它会以配置类所在的包作为基础包(base package)
- 为@ComponentScan设置基础包
- @ComponentScan的value属性中指明包的名称:
1.以string类型表示基础包
- @ComponentScan的value属性中指明包的名称:
设置多个基础包:
2.以类或接口所在的包表示基础包
除了将包设置为简单的String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所包含的类或接口:
可以看到,basePackages属性被替换成了basePackageClasses。同时,我们不是再使用String类型的名称来指定包, 为basePackageClasses属性所设置的数组中包含了类。这些类所在的包将会作为组件扫描的基础包。
2.4 通过为bean添加注解实现自动装配(@Autowired使用)
- 构造器上添加了@Autowired注解
这表明当Spring创建CDPlayerbean的时候,会通过 这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean。 - 属性的setter方法上添加了@Autowired注解
在Spring初始化bean之后,它会尽可能得去满足bean的依赖,在本例中,依赖是通过带有@Autowired注解的方法进行声明的,也就 是setCompactDisc()。 - 在类的任何上添加了@Autowired注解
使用@Autowired注解进行自动装配时,能否匹配的情况:
-
没有匹配的bean
如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属 性设置为false:
将required属性设置为false时,Spring会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状态。 但是,把required属性设置为false时,你需要谨慎对待。如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性有可能会 出现NullPointerException。 -
有多个匹配的bean 如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行自动装配
补充:@Autowired是Spring特有的注解。如果你不愿意在代码中到处使用Spring的特定注解来完成自动装配任务的话,那么你可以考虑将其替换 为@Inject:
3. 通过Java代码装配bean
尽管在很多场景下可以使用组件扫描和自动装配来实现spring自动化配置,但是在有些场景下是行不通的。比如你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添 加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了。
在这种情况下,你必须要采用显式装配的方式。在进行显式配置的时候,有两种可选方案:Java和XML
3.1 创建配置类
@Configuration注解所修饰的类就是配置类,该类中包含了应该在sprin应用上下文中如何创建bean的细节。
例如:
3.2 生命简单的bean
要在JavaConfig中声明bean,我们需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加@Bean注解
@Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终产生bean实例的逻辑。
1)默认情况下,bean的ID与带有@Bean注解的方法名是一样的。
2)设置成一个不同的名字的话,那么可以重命名该方法,也可以通过name属性指定一个不同的名字
3.3 借助javaconfig实现注入
1)在JavaConfig中装配bean的最简单方式就是引用创建bean的方法
2)在javaConfig中装配的另一种方式
通过这种方式引用其他的bean通常是最佳的选择,因为它不会要求将CompactDisc声明到同一个配置类之中。在这里甚至没有要求CompactDisc必须要在JavaConfig中声明,实际上它可以通过组件扫描功能自动发现或者通过XML来进行配置。你可以将配置分散到多个配置类、XML文件以及自动扫描和装配bean之中,只要功能完整健全即可。不管CompactDisc是采用什么方式创建出来的,Spring都会将其 传入到配置方法中,并用来创建CDPlayer bean
4. 通过配置文件装配bean
4.1 创建xml配合规范
最为简单的spring.xml配置如下所示:
4.2 在xml中声明bean
要在基于XML的Spring配置中声明一个bean,我们要使用spring-beans模式中的另外一个元素:。元素类似于JavaConfig 中的@Bean注解。
说明:1.创建一个bean的类是通过class属性指定的,要使用全限定名。 2、因为没有明确给定ID,所以这个bean将会根据全限定类名来进行命名;上述图中bean的id是“soundsystem.SgtPeppers#0”,其中“#0”是一个计数的形式,用来区分相同类型的其他bean。如果你声明了另外一个SgtPeppers,并且没有明确进行标识,那么它自动得到的ID将会是“soundsystem.SgtPeppers#1”。3、如果想为bean指定id,则通过id属性进行指定。
4.3 借助构造器初始化bean
构造器注入有两种方式: 1、<constructor-arg元素 2、使用Spring3.0所引入的c-命名空间
- 将bean的引用装配到构造器
1)使用 <constructor-arg 元素
2)使用Spring的c-命名空间
c-命名空间是在Spring 3.0中引入的,它是在XML中更为简洁地描述构造器参数的方式。 要使用它的话,必须要在XML的顶部声明其模式
三种形式:
1.
3.如果构造器中只要一个参数,根本不用去标示参数
- 将字面量装配到构造器
三种形式:
1.
2.通过参数索引装配相同的字面量值
3.如果构造器中只要一个参数,根本不用去标示参数
- 装配集合
在装配bean引用和字面量值方面,<constructor-arg和c-命名空间的功能是相同的。但是有一种情况“将集合装配到构造器参数中”是<constructor-arg能够实 现,c-命名空间却无法做到的
- 集合元素是普通的字面量
- 集合元素是bean
补充:当构造器参数的类型是java.util.List时,不管集合类型是字面量还是bean,也可以按照同样的方式使用元素:
4.4 设置属性
通过属性的setter方法实现依赖注入
4.4.1 设置属性(引入其他bean)
1.通过<property实现依赖注入
2.通过p-命名空间实现依赖注入
Spring为元素提供了c-命名空间作为替代方案,与之类似,Spring提供了更加简洁的p-命名空间,作 为元素的替代方案。为了启用p-命名空间,必须要在XML文件中与其他的命名空间一起对其进行声明:
使用p-命名空间:
4.4.2 设置属性(字面量)
1.通过<property实现依赖注入
2.通过p-命名空间实现依赖注入
3.通过p-命名空间实现集合依赖注入
我们不能使用p-命名空间来装配集合,没有便利的方式使用p-命名空间来指定一个值(或bean引用)的列表。但是,我们可 以使用Spring util-命名空间中的一些功能来简化BlankDisc bean。
首先,需要在XML中声明util-命名空间及其模式:
util-命名空间所提供的功能之一就是util:list元素,它会创建一个列表的bean。借助util:list,我们可以将磁道列表转移 到BlankDisc bean之外,并将其声明到单独的bean之中,如下所示:
现在,我们能够像使用其他的bean那样,将磁道列表bean注入到BlankDisc bean的tracks属性中:
5. 导入和混合配置
在Spring中,可以将JavaConfig的组件扫描和自动装配和/或XML配置混合在一起
混合配置,在自动装配时,它并不在意要装配的bean来自哪里。自动装配的时候会考虑到Spring容器中所有的bean,不管它是在JavaConfig或XML中声明的还是通过组件扫描获取到的。
你可能会想在显式配置时,比如在XML配置和Java配置中该如何引用bean呢
5.1 在JavaConfig中引用XML配置
- 在一个javaconfig中引入另外一个javaconfig
-
创建一个更高级的SoundSystemConfig,在其中使用@Import将两个配置类组合在一起
-
在一个javaconfig中引入XML来配置
5.2 在XML配置中引用JavaConfig
- 在一个xml配置中引入另外一个xml配置
-
在一个xml配置中引入一个javaConfig配置
元素能在xml配置文件中导入javaConfig配置类 -
创建一个更高层次的配置文件,这个文件不声明任何的bean,只是负责将两个或更多的配置组合起来