在《Spring 基本使用》一节中,Spring Bean的装配方式是:组件扫描和@Autowired自动装配。有时候自动化配置方案行不通,需要明确配置Sring。比如你需要将第三方组件装配到你的应用中。在这种情况下,你是没有办法在它的类上加上@Component和@Autowired注解的,因此,在这种情况下,便不能使用自动装配了。
在无法使用自动装配时,你只能使用显示的装配方案,可选的有两种Java配置和XML配置。
在进行显示配置时,JavaConfig是更好的方案,因为它更加强大,类型安全,并且重构友好。因为它就是Java代码,和你应用中其他的Java代码一样。同时,JavaConfig又和其他的Java代码有所区别,在概念上,它与应用程序中的业务逻辑和领域代码是不同的。尽管它与其他组件一样都使用同一语言进行描述,但是JavaConfig是配置代码,这意味着它不应该包含任何的业务逻辑代码。JavaConfig也不应该侵入其他的业务逻辑代码中。尽管不是必要的,一般将JavaConfig放在放在一个单独的包中,使其与业务逻辑代码相分离。
1.通过JavaConfig来显示的配置Spring
(1)创建配置类
package com.hsun.spring.config;
import org.springframework.context.annotation.Configuration;
/**
* 创建JavaConfig的关键在于为配置类加上@Configuration注解,
* 该注解表明这个类是一个配置类,该类应该包含SPring如何创建bean的细节
* @author hsun
*
*/
@Configuration
public class MyConfig {
}
在《Spring 基本使用》中,使用的都是组件扫描的方式来发现Spring应该创建的Bean。尽管我们可以同时使用组件扫描和显示配置,在此只关注显示配置,故而将注解@ComponentScan移除。
(2) 创建Bean
@ComponentScan告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。在此配置类中移除了此注解,组件扫描将不会发现那些我们希望被Spring发现并且创建的Bean。
针对这样的情况我们可以在JavaConfig中显示配置一个bean,编写一个方法,这个方法负责创建我们所需要的bean的实例,并在该方法上加上@Bean注解。
@Bean
public CompactDisc setPeppers() {
return new CompactDisc();
}
@Bean注解会告诉Spring注解这个方法将返回一个对象,该对象要注册成为Spring应用上下文的bean。方法体中包含了最终产生bean实例的逻辑。默认情况下这种方式创建的bean的ID与创建该bean的方法的方法名是一样的。在以上的示例代码中,创建产生的bean的id将会是setPeppers。如果需要为其设置一个其他的名字的话,那么可以修改方法的名称或者也可以通过name属性指定一个不同的名字:
@Bean(name="lonelyHeartClubBand")
public CompactDisc setPeppers() {
return new CompactDisc();
}
当然使用JavaConfig创建Bean不仅仅只有这一点功能,使用JavaConfig创建bean仅仅与创建bean的方法体内的代码逻辑相关。那么如下,可以根据不同的情况来创建不同的bean:
@Bean
public CompactDisc randomBeatlesCD() {
int choice = (int)Math.floor(Math.random()*4);
switch (choice) {
case 0:
return new Sgtppers();
case 1:
return new WhiteAlbum();
case 2:
return new HardDaysNight();
default:
return new Revolver();
}
}
(3)借助JavaConfig实现注入
之前声明的CompactDisc Bean都是非常简单的Bean它自身没有其他的依赖,但是若土国声明CDPlayer Bean,并且该Bean依赖ComPactDisc。在JavaConfig中想要将其装配到一起,最简单的方法就是引用创建Bean的方法,如下是一种声明CDPlayer的可行的方案:
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(setPeppers());
}
当然除了以上的通过方法的引用来实现装配外,也可以通过参数传递的方式来实现装配:
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
通过参数引用其他bean的方式通常是最佳的选择。因为他不要求将CompactDisc Bean声明到同一个配置类中。甚至你不需要将ComapctDisc声明到JavaConfig配置类中,实际上他可以通过组件扫描发现或者通过XML配置。你可以将这些配置分散到多个配置类或者配置文件以及自动扫描装配bean之中。只要功能完全健全即可。不管CompactDisc是通过什么方式创建的,Spring都会就将其传入配置方法中,并用其创建CDPlayer。
另外,此处使用的是Bean的构造器实现了DI功能,但是我们完全可以采用其他风格的DI配置。比如说通过Setter来注入CompactDisc:
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
CDPlayer cdPlayer =new CDPlayer(compactDisc);
cdPlayer.setCompactDisc(compactDisc);
return cdPlayer;
}
2.通过XML来装配bean
在使用XML来装配Bean之前你需要创建一个Spring的XML配置规范,即创建一个Spring的配置文件,最简单的Spring XML配置如下所示:
(1)声明一个简单的<bean>
要在基于Spring XML的配置中声明一个bean,需要使用spring-beans模式中两个元素<beans>、<bean>。<beans>元素包裹<bean>,声明一个简单的bean如下:
这里声明了一个简单的bean,创建这个bean的类是通过class属性指定的,并且要使用全限定类名。因为没有明确的指定ID,所以这个bean将会只用全限定类名来进行命名。bean的ID将会是
其中“#0”是一个计数形式,用来区分相同类型的其他bean实例。如果声明了另外一个SgtPeppers,并且没有明确进行你标识,那么自动得到的ID将会是
当然也可以通过id属性来为每一个创建的bean来指定一个你选择的名字:
在将这个bean装配到其他的bean中时你将会使用到这个名字。
(2)借助构造器初始化bean
a.简单的构造器初始化
在Spring 的XML配置中只有一种声明Bean的方式,使用bean元素并指定class属性,Spring将从这里获取必要信息来创建bean。但是在XML中声明DI时,却有多中可选的配置方案和风格。具体到构造器注入有两种可选择的方案:
-
使用<constructor-arg>元素
-
使用Spring 3.0所引入的c-命名空间
先在spring xml配置文件中声明 c-的命名空间:
使用c-命名空间来声明构造器参数:
使用c-声明构造器参数的属性名构成:
或者将构造器参数替换成“0”,也就是将参数名替换成参数索引,因为XML文件不允许数字做为属性的第一个字符,因此必须要添加一个下划线作为前缀:
如果这有一个构造器参数,那么还可以写成这样:
b.将字面量注入到构造器中
再次使用<constructor-arg>来进行构造器的参数注入,但是此时使用的是"value"而不是“ref”,通过“value”属性表明,给定值要通过字面量的形式注入到构造器中。
通过c-命名空间:
或者
当然如果只有一个构造器参数,那么你当然可以写成这样:
c.装配集合
类似的可以使用“ref”来替代”value“
当构造器参数是java.util.List时,使用<list>是合情合理的,尽管如此,我们同样可以按照同样的方式来使用<set>元素:
d.设置属性
使用p-命名空间:
使用spring-util-命名空间来声明list,配bean的属性注入:
3. 导入和混合配置
(2)JavaConfig引用
或者编写一个更加高级的配置类将两个配置类组合在一起:
(2)JavaConfig引用XML配置
(3)在XML配置中引用JavaConfig
配置文件组合: