Spring提供了三种wiring机制
在xml文件里声明
在java中声明
让Bean自动发现、自动装配
1. 自动装配Bean
Component scanning:自动扫描发现Bean
Autowiring:自动装配Bean依赖
1.1 创建可以被发现的Bean
- 使用注解@ComponentScan,启用自动扫描功能
- 在需要被发现的Bean上使用注解@Component
package soundsystem;
public interface CompactDisc {
void play();
}
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);
} }
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
@Component注解表明当前类是一个可以被Spring进行管理的Bean
@Configuration注解表明当前是一个配置类,并自动配置
@ComponentScan注解来启用自动扫描component,默认扫描当前包
也可以使用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"
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>
测试:
package soundsystem;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
命名一个可以被扫描的Bean(给Bean命名)
默认情况下,bean的ID、name是Bean的类名(首字母小写)。
1.2 给Bean命名:
- 直接在@Component注解中进行配置
@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
...
}
- 使用@Named注解,@Named是@Component的一种替代,但是不建议使用
package soundsystem;
import javax.inject.Named;
@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
...
}
1.3 设置包扫描路径
直接在@ComponentScan注解中进行配置:
@Configuration
@ComponentScan("soundsystem")
public class CDPlayerConfig {
}
或使用@ComponentScan的basePackages属性
@Configuration
@ComponentScan(basePackages={"soundsystem", "video"})
public class CDPlayerConfig {
}
或使用@ComponentScan的basePackageClasses属性
@Configuration
@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
public class CDPlayerConfig {
}
1.4 自动装配Bean
- 使用@Autowired注解:
@Autowired注解可以使用在:
1.1 构造方法上
1.2. 任意方法上
1.3. 属性上
注意: 默认是required的,也就是说所注入的Bean必须是存在的,如果允许注入的Bean不存在,则将required设为false即可,即@Autowired(required=false)
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
private CompactDisc1 cd1;
@Autowired
private CompactDisc2 cd2;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
@Autowired
public void insertDisc(CompactDisc1 cd1) {
this.cd1 = cd1;
}
}
- 使用@Inject注解
package soundsystem;
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class CDPlayer {
@Inject
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
}
2. 用java装配Bean
两种方式:
- java
- xml
这里我们只关注java方式的。
2.1 创建配置类
使用@Configuration注解
package soundsystem;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
}
2.2 声明一个Bean
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
@Bean注解告诉Spring这个方法将会返回一个对象,这个对象需要被Spring Context管理。
默认情况下,bean的ID和方法名一样
可以对bean的name进行命名:
@Bean(name="lonelyHeartsClubBand")
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
2.3 通过Java配置类来进行Bean注入
2.3.1 直接通过调用方法进行注入
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}
注意:Spring在这里会拦截调用方法sgtPeppers,并不会再一次真正的调用它,而是使用它已经初始化过的Bean。
默认情况下,Spring中的Bean都是单例的。
2.3.2 通过方法参数进行注入
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
2.4 通过XML来装配Bean
2.4.1 创建一个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"
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
<bean class="soundsystem.SgtPeppers" />
默认会生成一个ID-----soundsystem.SgtPeppers#0,这个#0是自动生成的、用来和其他同类型的Bean做区分的。
<!--显示声明id-->
<bean id="compactDisc" class="soundsystem.SgtPeppers" />
2.4.3 通过构造方法注入Bean
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="compactDisc" />
</bean>
2.4.4 设置属性
<bean id="cdPlayer"
class="soundsystem.CDPlayer">
<property name="compactDisc" ref="compactDisc" />
</bean>
2.5 混合配置
实际情况下,会使用xml加javaConfig来共同进行配置。
2.5.1 在java配置类中引用XML配置
可以使用@Import注解将多个配置类进行整合
@Configuration
public class CDConfig {
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
}
@Configuration
@Import(CDConfig.class)
public class CDPlayerConfig {
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
}
@Configuration
@Import({CDPlayerConfig.class, CDConfig.class})
public class SoundSystemConfig {
}
在Java配置类中引用XML配置文件:
使用@ImportResource注解
<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>
@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {
}
2.5.2 在XML配置文件中引用java配置
可以使用 <import>标签来引用其他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">
<import resource="cd-config.xml" />
<bean id="cdPlayer"
class="soundsystem.CDPlayer"
c:cd-ref="compactDisc" />
</beans>
使用<bean> 标签来引入Java配置类:
<?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" />
<bean id="cdPlayer"
class="soundsystem.CDPlayer"
c:cd-ref="compactDisc" />
</beans>
<?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>