Bean -- 一种表达实体和信息的规范,便于封装重用。
Bean有以下特点:
1、所有属性为private 2、提供默认构造方法 3、提供Setter和Getter 4、实现Serializable接口
Spring装配Bean三种方式: XML显式配置、Java显式配置、自动装配。
一、自动装配
Spring通过以下两个角度来实现自动化装配
1、组件扫描:Spring会自动发现应用上下文中所创建的bean
2、自动装配:Spring自动满足bean之间的依赖
接下来以一个CD播放器的例子来演示自动装配
首先定义媒体播放器和CD两个接口
package soundsystem;
public interface MediaPlayer {
void play();
}
package soundsystem;
public interface CompactDisc {
void play();
}
定义CD播放器类实现媒体播放器接口
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CDPlayer implements MediaPlayer{
private CompactDisccd;
@Autowired
public CDPlayer(CompactDisc cd){
this.cd = cd;
}
@Override
public void play() {
cd.play();
}
}
@Component注解表明该类会作为组件类,并告知Spring为这个类创建bean
@Autowired注解表明当Spring创建CDPlayer bean 的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean。
@Autowired注解可以用在类的任何方法上,还可以用于成员变量上。@Inject源于Java依赖注入规范,在大多场景下可与@Autowired互换。
然后定义一个SgtPeppers类,它实现了CompactDisc接口,也是一个组件类。
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";
@Override
public void play() {
System.out.println("Playing "+title+" by "+artist);
}
}
最后定义一个CDPlayer配置类
package soundsystem;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
@Configuration代表这是一个配置类
@ComponentScan表示启用组件扫描
组件扫描可以在一个CD播放器一张CD的时候正常工作,但是在有两张CD的时候就不能正常工作了,因为它不知道应该播放哪一张CD,这里我们只有一张披头士的CD,关于多张CD的情况留到后面处理。
我们也可以用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"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
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>
<context:component-scan base-package="soundsystem" />表示会在soundsystem这个包内找合适的bean注入到CDplayer
现在定义CDPlayerTest类测试一下
package soundsystem;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
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 {
@Rule
public final StandardOutputStreamLoglog =new StandardOutputStreamLog();
@Autowired
private MediaPlayerplayer;
@Autowired
private CompactDisccd;
@Test
public void cdShouldNotNull(){
assertNotNull(cd);
}
@Test
public void play(){
player.play();
assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n",log.getLog());
}
}
@ContextConfiguration(classes = CDPlayerConfig.class)会使用CDPlayerConfig这个类来配置应用上下文。
下面试试使用XML配置
package soundsystem;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
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(locations ="classpath:soundsystem.xml")
public class CDPlayerXMLConfigTest {
@Rule
public final StandardOutputStreamLoglog =new StandardOutputStreamLog();
@Autowired
private MediaPlayerplayer;
@Autowired
private CompactDisccd;
@Test
public void cdShouldNotNull(){
assertNotNull(cd);
}
@Test
public void play(){
player.play();
assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n",log.getLog());
}
}
@ContextConfiguration(locations ="classpath:soundsystem.xml")会使用soundsystem.xml来配置应用上下文。
二、Java显式配置
媒体播放器和CD接口保持不变
接下来看看CD播放器类与自动装配有什么不同之处
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
public class CDPlayer implements MediaPlayer {
private CompactDisccd;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
与自动装配比较可以发现类声明上面少了@Component注解 我们没有将CDPlayer声明为一个组件类
SgtPeppers类也没有@Component注解
重点来看看CDplayerConfig类
package soundsystem;
import org.springframework.context.annotation.*;
@Configuration
public class CDPlayerConfig {
@Bean
public CompactDisc compactDisc(){
return new SgtPeppers();
}
@Bean
public CDPlayer cdPlayer(CompactDisc cd){
return new CDPlayer(cd);
}
}
这里没有@ComponentScan注解然后在配置类中自己定义了两个bean从第一个bean可以看到如果需要注入CompactDisc bean的时候注入的是SgtPeppers类对象,需要注入CDPlayer bean 时注入的时候注入的是CdPlayer对象。
总结一下:Java显式配置与自动装配主要区别在配置类上,Java配置需要显示地声明bean,自动装配配置类有@ComponentScan注解,它会自动扫描带有@Component注解的bean来将其注入到合适的地方。
三、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">
<bean id="compactDisc" class="soundsystem.SgtPeppers" />
<bean id="cdPlayer" class="soundsystem.CDPlayer"
c:cd-ref="compactDisc" />
<bean id="compactDisc" class="soundsystem.SgtPeppers" />
@Bean
public CompactDisc compactDisc(){
return new SgtPeppers();
}
上述的一行XML配置和上面的一段Java配置起到的作用是一样的。
XML中参数的声明是由<constructor-arg>标签来实现,想要注入一个集合可以使用<list>标签包裹集合内所有项
使用<value>标签包裹集合内的一项。
<bean id="compactDisc"
class="soundsystem.BlankDisc"
c:_0="Sgt. Pepper's Lonely Hearts Club Band"
c:_1="The Beatles">
c:_0代表构造器的第一个参数,c:_1代表构造器的第二个参数。
四、混合配置
package soundsystem;
import org.springframework.context.annotation.*;
@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {
}
加粗的两个注解从一个Java配置类和一个XML文档加载上下文。