【Spring系列(2)】Bean的裝配 Autowired, XML配置, Java顯式配置
Bean的装配
任何一个优秀的应用都是由多个为了实现某一个业务目标而相互协作的组件构成的。而创建对象之间的关联关系的传统方法一般是通过构造器或者查找,很难复用,也很难测试。在Spring中,对象不需要自己查找或者创建与其关联的其他对象,容器负责把需要相互协作的对象引用赋予各个对象。
例如,一个订单管理组件需要信用卡认证的组件,他不需要自己去创建这个组件,反之,容器会主动赋予它一个信用卡认证的组件。
这种创建对象之间的协作关系的行为叫做装配(wiring), 这其实是依赖注入的本质了。
Spring配置的方案
在上一讲中我们说了Spring的容器,其负责创建应用程序当中的Bean并通过依赖注入的方式来协调这些对象之间的关系。而开发人员需要做的是, 告知容器,要创建哪些Bean,并且如何将其拼装在一起 , Spring提供了三种装配的方式:
在XML中配置
在Java中配置
隐藏的bean发现机制和自动装配 (autowiring)
这三种方式,autowiring的方法有自己的一些使用限制,因为其在引用第三方的库的时候,是无法自动装配的,而在XML和Java中显式配置是等价的,但是Java下更有利于类型安全,下面通过例子来对这三种方式分别进行分析:
自动化装配Bean
Spring从两个角度来实现自动化装配的:
组件扫描(component scanning): Spring会自动发现应用上下文中所创建的Bean
自动装配(autowiring): Spring自动满足应用之间的依赖
创建几个Bean,代表一个音响系统的组件:
public interface CompactDisc { void play(); }
CD播放器在这里定义了一个接口,他的具体实现(如何播放)和哪一张CD没有关系,通过这种方式达到解耦合的目的。
@Component //Spring会给Bean配置一个ID,默认的是sgtPeppers,即类名,第一个字母小写public class SgtPeppers implements CompactDisc { private String title = "Yi ran yi bao zha"; private String artist = "Li Chen"; public void play() { System.out.println("Playing " + title + " by " + artist); } }
这里提供了CD播放器的具体实现,这里要注意注释 @Component, 是告诉Spring,这个类会作为组件类,需要Spring为其创建bean(不再需要显式的声明Bean了)
组件扫描默认是不启用的,因此我们需要显式配置一下Spring,命令其去寻找带有@Component的注解的类,并为其创建Bean。
@Configuration@ComponentScan // 启用了组件扫描public class CDPlayerConfig { // 这里默认会再同一个包下进行搜索,但是也可用通过basePackages属性来进行搜索范围的设置 // @ComponentScan(basePackage = {"soundSystem", "video"}) 这里使用String进行范围配置 // @ComponentScan(basePackage = {"CDPlayer.class", "DVDPlayer.class"}) 也可以使用类来进行配置 }
进行测试,看是否进行了自动装配
@RunWith(SpringJUnit4ClassRunner.class) // 容器,以便自动创建Spring的应用上下文@ContextConfiguration(classes=CDPlayerConfig.class) // 需要加载配置public class CDPlayerTest { @Autowired // 将bean注入到test的代码当中来 private CompactDisc cd; @Test public void cdShouldNotBeNull() { assertNotNull(cd); } }
给bean命名,可以用@Component 也可以用@Named
@Component("your_name") // spring package@Named("your_name") // javax.inject.Named
上述说明的是ComponentScan相关的内容,因为上述的Bean是相互独立的,即在使用的时候,并没有对于其他的Bean的依赖。但是很多对象会依赖其他对象才可以完成任务,我们需要一种方法能够将组件扫描得到的bean和他们的依赖装配在一起——自动装配(Autowiring)
@Autowired
@Componentpublic class CDPlayer implements MediaPlayer { private CompactDisc cd; @Autowired public CDPlayer(CompactDisc cd) { this.cd = cd; } public void play() { cd.play(); } }
在这个例子里,Autowired注解被用在了构造器当中。这表明当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并会传入一个可以设置给CompactDisc类型的bean。
@RunWith(SpringJUnit4ClassRunner.class) // 容器,以便自动创建Spring的应用上下文@ContextConfiguration(classes=CDPlayerConfig.class) // 需要加载配置public class CDPlayerTest { @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Autowired // 将bean注入到test的代码当中来 private CompactDisc cd; @Autowired private MediaPlayer player; @Test public void cdShouldNotBeNull() { assertNotNull(cd); } @Test public void play() { player.play(); assertEquals("Yi ran yi bao zha" + "Li Chen\n", log.getLog()); } }
通过Java代码装配Bean
自动化配置在要引入第三方库当中的组件的时候,是无法执行的。在这种时候我们要选择显式配置的方案,
在Java中显式配置
在XML中显式配置
JavaConfig相对来说是更好的方案,因为其更强大,类型安全,对重构友好
值得注意的是
JavaConfig是配置代码,这意味着其不应该包含任何业务逻辑,也不应该侵入到业务逻辑代码当中去。习惯做法,是放到单独的包中,使其与其他的应用程序逻辑分离开。
@Bean // Bean注解告诉Spring要返回一个对象,要注册为Spring应用上下文的beanpublic CompactDisc sgtPeppers() { return new SgtPeppers(); }@Beanpublic CDPlayer cdPlayer() { return new CDPlayer(sgtPeppers());
作者:石头堆1566
链接:https://www.jianshu.com/p/a4a055aabede
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章