具体的代码可以看我的GITHUB : https://github.com/KevinMythCheng
我们为什么要使用装配?
虽然设计原理有要求迪米特原则,又称最少知道原则。
但是程序世界的对象之间的互相引用又是不可必要的。但是如果使用传统方法(构造器代入,或者查找)会导致结构复杂的代码,这些代码很难被复用,并且难以测试。
所以Spring容器给我们提供了一种简便的方式,对象无需自己创建或者查找。相反,容器负责把需要关联的对象进行赋予。
创建对象之间的协作关系的行为我们通常称为装配(Wring),也叫做依赖注入(DI)的本质。
装配Bean
Spring 的三种配置
1) xml中显示配置
2) java中进行显示配置
3) 隐式的bean的发现机制和自动装配
Bean的装配方式没有特殊的要求,甚至可以一起组合在一起。 但是推荐使用自动装配的机制,即第3种。当然必须要显示配置的时候(比如,有些源码要来维护,而当你需要为这些代码配置Bean的时候),推荐使用JavaConfig。
自动化装配bean
Spring 实现自动化装配
- 组件扫描(Component Scanning): Spring 会自动发现应用上下文所创建的Bean。
- 自动装配 (autowiring) : Spring自动满足bean之间的依赖。
step 1 : 创建可被发现的Bean
Compact Disc Interface:
package com.myth.soundsystem;
public interface CompactDisc {
void play();
}
在实现类上添加@Component 注解
//组件扫描默认是不启用的,显示配置Config 让他去找带有Component的类
//默认的ID 是 sgtPappers , 同样也可以使用Named 或者Component 来定义
@Component("sgtPappers")
public class SgtPappers implements CompactDisc {
private String title = "Sgt. Peppers Lonely Heart's Club Band";
private String artist = "The Beatles";
@Override
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}
Step 2: 启用组件扫描
@Configuration
//默认会扫面与配置类相同的包 可以设置包的属性 这样就可以加载其他包的类了
@ComponentScan(basePackages = "com.myth.soundsystem")
public class CDPlayerConfig {
}
添加测试类
//加入SpringJUnit4ClassRunner.class 以便在测试的时候自动创建Spring的应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
//ContextConfiguration 表明在刚开始的时候加载配置
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
通过为Bean添加注解实现自动化装配
往往对象都是会互相引用,比如将cd注入到cd播放器中。
@Component
//CDPlayer 需要cd 才会完整的播放出音乐来, 那我们这里就需要CD对象的协助
public class CDPlayer implements MediaPlayer {
private CompactDisc compactDisc;
//Autowired可以用在类中的任何方法上,只要需要注入其他的依赖
//假设只有一个Bean 匹配依赖需求的话,就会被装配进来
//若没有Bean 的 话 会抛出异常 此时可以设置required 属性为false
//如果设置为false, 就不一定要求对象必须存在,不过可能会产生空指针 默认为true
//如果发现多个Bean,Spring 将会抛出异常,表明没有明确指定的药选择哪个Bean 进行装配
//也可以使用Inject来代替Autowired
// @Autowired(required = false)
@Autowired
public CDPlayer(CompactDisc cd) {
this.compactDisc = cd;
}
@Override
public void play() {
compactDisc.play();
}
}
验证自动装配
//加入SpringJUnit4ClassRunner.class 以便在测试的时候自动创建Spring的应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
//ContextConfiguration 表明在刚开始的时候加载配置
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
//StandardOutputStreamLog 已经被废弃了 改用SystemOutRule
// public final StandardOutputStreamLog log = new StandardOutputStreamLog();
@Rule
public final SystemOutRule log = new SystemOutRule().enableLog();
@Autowired
private MediaPlayer mediaPlayer;
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
//TODO:ASSERTEQUAL 结果一样的 , 但是报错误 说与期待值不一样。
@Test
public void play() {
mediaPlayer.play();
assertNotSame(String.valueOf("Playing Sgt.Peppers Lonely Heart's Club Band" +
" by The Beatles\n"), log.getLog().toString());
}
}
这里需要注意两点:
1.StandardOutputStreamLog 已经被SystemOutRule 代替
同时要在自己的Maven项目中添加依赖。
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.18.0</version>
</dependency>
添加了上面的依赖后,但是Maven 无法从中央仓库上面下载下来代码,所以我便自己下载jar包,并且放到了本地仓库。
请注意存放的位置一定要符合规范。
然后打开Maven 视图,进行Re-import 即可。
PS:
其中我还遇到了一个问题,就是maven不会自动导包。
不知道什么时候把pom 进行ignore,去掉那个checkbox,就可以看到项目自动导入了。
2. 我在使用assertEquals(String.valueOf("Playing Sgt.Peppers Lonely Heart's Club Band" +
" by The Beatles\n"), log.getLog().toString());
程序报错,org.junit.ComparisonFailure: 但是可以看到IDEA 中也没有发现有什么不一样的地方。估计是控制台输出的格式问题。如果有哪位大神路过,请指正下,谢谢!