Spring 从两个角度实现自动化装配:spring
CD 为咱们阐述依赖注入是如何运行的。若是你不将CD插入(注入)到CD播放器中,那么CD播放器没有什么太大用处。因此,能够说,CD播放器依赖于CD才能完成它的使命。
首先,咱们定义一个CD的概念,一个接口:数组
package soundsystem; public interface CompactDisc { void play(); }
做为接口,它定义了CD播放器对一盘CD所能进行的操做。咱们如今还须要一个实现类。安全
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); } }
SgtPeppers类上使用了 @Component 注解。
@Component:这个注解代表该类回座位组件类,并告知Spring要为这个类建立bean。ide
不过,组件扫描默认是不启用的。咱们还须要显示配置一下spring,从而命令它去寻找带有@Component注解的类,并为其建立bean。测试
package soundsystem; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan public class CDPlayerConfig { }
CDPlayerConfig类并无显示地声明任何bean,只不过它使用了@ComponentScan注解,这个注解可以在Spring中启用组件扫描。若是没有其余配置的话,@ComponentScan默认会扫描与配置类相同的包。
测试类作一个简单的测试。this
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); } }
注解 @ContextConfiguration 会告诉它须要在 CDPlayerConfig 中加载配置。由于 CDPlayerConfig 类中包含了 @ComponentScan ,所以最终的应用上下文中应该包含 CompactDisc bean。code
Spring应用上下文中全部的bean都会给定一个ID。默认为会根据类名指定一个ID,也就是将类名的首字母变为小写。若是想单独设置ID能够在后追加名称对象
@Component("xxxxxx")
咱们没有为 @ComponentScan 设置任何属性,按照默认规则,它会以配置类所在的包做为基础包(base package)来扫描组件,若是咱们想扫描不一样的包,咱们能够在 @ComponentScan 的 value 属性中指明包的名称:接口
@Configuration @ComponentScan("soundsystem") public class CDPlayerConfig {}
若是你想更加清晰地代表你所设置的死基础包,那么你能够经过 basePackages 属性进行配置:get
@Configuration @ComponentScan(basePackages="soundsystem") public class CDPlayerConfig {}
basePackages 属性使用的复数形式,因此咱们能够设置多个基础包,只须要将 basePackages 属性设置为要扫描包的一个数组便可:
@Configuration @ComponentScan(basePackages={"soundsystem", "video"}) public class CDPlayerConfig {}
上面的例子是以 String 类型表示的。显然这种方法是不安全的,若是重构代码的话,那么所指定的基础包可能就会出现错误。因此咱们可使用另一种方法,将其指定为包中锁包含的类或接口:
@Configuration @ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class}) public class CDPlayerConfig {}
其实最好的方法,能够考虑在包中建立一个用来进行扫描的空标记接口,依然可以保持对重构友好的接口引用,可是能够避免引用任何实际的应用程序代码。
在你的应用程序中,若是全部对象都是独立的,彼此之间没有任何依赖,那么你所须要的就只是组件扫描而已。可是,不少对象会依赖其余的对象才能完成任务。这样的话,咱们就须要一种方法可以将组件扫描获得的 bean 和它们的依赖装配在一块儿。也就是自动装配。
简单来讲,自动装配就是让Spring自动知足bean依赖的一种方法,在知足依赖的过程当中,会在Spring应用上下文中寻找匹配某个bean需求的其余bean。为了声明要进行自动装配,咱们能够借助Spring的 @Autowired 注解。
package soundsystem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class CDPlayer implements MediaPlayer { private CompactDisc cd; @Autowired public CDPlayer(CompactDisc cd) { this.cd = cd; } public void play() { cd.play(); } }
在构造器上加注解,代表当 Spring 建立 CDPlayer bean的时候,会经过这个构造器来进行实例化而且会传入一个可设置给 CompactDisc 类型的bean。
无论是构造器、Setter 方法仍是其余的方法,Spring 都会尝试知足方法参数上所声明的依赖。假若有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。