@Autowired 注解不仅能够用在构造器上,还可以用在类的任何方法上。如果没有匹配的 bean 的话,那么在应用上下文创建的时候,Spring 会抛出一个异常,为了避免异常,需要在给@Autowired 的 required=false,需要注意的是若是bean 忘记装配,要记得作 null 的判断,否则还是会出现异常的。
现在把 CDPlayerConfig 修改成下面:
package com.springinaction.soundsystem; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * Created by user on 2/21/17. */ @Configuration @ComponentScan(basePackageClasses = {MediaPlayer.class}) public class CDPlayerConfig { }
这里的 CDPlayer 与 MediaPlayer 都是接口,而不用实例,这么做的好处是重构友好,避免引用任何实际的实例,如果这些实例想在重构的过程中删除的话,就不会有麻烦了。
MediaPlayer 接口:
package com.springinaction.soundsystem; /** * Created by user on 2/22/17. */ public interface MediaPlayer { void play(); }
CDPlayer 变成这样了:
package com.springinaction.soundsystem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * Created by user on 2/22/17. */ @Component public class CDPlayer implements MediaPlayer { private CompactDisc cd; @Autowired public CDPlayer(CompactDisc cd){ this.cd = cd; } public void play(){ cd.play(); } }
CDPlayerTest 类:
package com.springinaction.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; /** * Created by user on 2/21/17. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc cd; @Autowired private CDPlayer player; @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Test public void cdShouldNotBeNull(){ assertNotNull(cd); } @Test public void play(){ player.play(); assertEquals("Playing Sgt. Pepper's Lonly Hearts Club Band by The Beatles\n",log.getLog()); } }
这里的 StandardOutputStreamLog 已经过时了,编辑器不建议使用,上面的代码中没有体现出来。它是来源于 System Rules库的一个 JUnit 规则,该规则能够基于控制台的输出编写断言。了解一下就好。运行之后: