【SpringInAction】装配 Bean

具体的代码可以看我的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 中也没有发现有什么不一样的地方。估计是控制台输出的格式问题。如果有哪位大神路过,请指正下,谢谢!

 

通过JavaConfig 来装配Bean

Step 1: 创建配置类 不使用包扫描

Step 2:声明简单的Bean  在java config 中声明Bean 包括名称等等

Step3:借助Java Config实现注入  在另一个对象中引用之前声明的对象,当然可以使用构造器或者Set 的方法进行注入

@Configuration
//默认会扫面与配置类相同的包 可以设置包的属性 这样就可以加载其他包的类了
//使用JAVAConfig 的方式 进行配置 去除掉@ComponentScan
//@ComponentScan(basePackages = "com.myth.soundsystem")
public class CDPlayerConfig {

//在JavaConfig中创建Bean的实例
//同样的可以设置Bean 的名称
@Bean(name = "sgtPappers")
public CompactDisc sgtPappers() {
return new SgtPappers();
}

//在CDPlayer中注入一张cd sgtPappers
/* @Bean
public CDPlayer cdPlayer(){
return new CDPlayer(sgtPappers());
}*/

//因为Spring 是单例的 , 所以这两个sgtPappers 其实是一个
//可以使用带参数的方式进行注入,这样子不用每次在Java Config中声明Bean 可以使用注解的方式或者XML 的方式
@Bean
public CDPlayer anotherCDPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
}

 通过XML 的方式

现在基本不再使用,建议使用自动配置或者JavaConfig。

 





posted on 2018-06-28 01:05  哆啦任意门  阅读(439)  评论(0编辑  收藏  举报

导航