Spring对bean的装配机制(一)——隐式自动装配 妖狐艹你老母 2021-09-26 06:32 232阅读 0赞 Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,那Spring装配bean时是如何装配的呢? Spring非常灵活,它提供了三种主要的装配机制: 1.隐式的bean发现机制和自动装配。 2.在xml中进行显式装配。 3.在Java中进行显式装配。 本文对第一种机制进行详细说明: # 一.自动装配bean # ## spring从两个角度来实现自动化装配: ## \*.组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean. \*.自动装配(autowiring):Spring自动满足bean之间的依赖. 说明:自动装配bean有两种方式,一种是java代码直接注解的形式,一种是xml配置的形式。xml配置的形式是目前国内大部分公司在用的,java代码直接注解的用的不多,不过个人觉得比xml的形式方便很多。 ## (一)java形式的自动装配 ## ### 1.创建一个CompactDisc接口 ### package soundsystem; /** *@作者:JackHisen(gwd) *@email:1154978352@qq.com *@时间:2017年7月29日 下午7:20:50 *@version 1.0 */ public interface CompactDisc { void play(); } ### 2.创建CompactDisc接口的实现类 ### /** *@作者:JackHisen(gwd) *@email:1154978352@qq.com *@时间:2017年7月29日 下午7:21:38 *@version 1.0 */ @Component//@Component("sgtPeppers")可以通过这样的方式来给bean设置id public class SgtPeppers implements CompactDisc { private String title="Sgt.Pepper's Lonely Hearts Club Band"; private String artist="The Beatles"; public void play() { // TODO Auto-generated method stub System.out.println("Playing"+title+"by"+artist); } } SgtPeppers的具体内容并不重要,你需要注意的是SgtPeppers类上的@Component注解。这个简单的注解表名该类会作为组件类,并告知Spring要为这个类创建bean。没有必要显式配置SgtPeppers bean,因为这个类使用了@Component注解,所以Spring会为你把事情处理妥当。 不过,组件扫描默认是不启用的,所以我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。CDPlayerConfig类展示了完成这项任务最简洁的配置。 注:还有另外一种bean命名的方式,这种方式不使用@Component注解,而是使用Java依赖注入规范中所提供的@Named注解来为bean设置ID。Spring支持将@Named作为@Component注解的替代方案。两者之间有些细微的差异,但是在大多数场景中,他们它们是可以相互替换的。 ### 3.开启组件扫描 ### package soundsystem; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** *@作者:JackHisen(gwd) *@email:1154978352@qq.com *@时间:2017年7月29日 下午7:24:49 *@version 1.0 */ @Configuration @ComponentScan public class CDPlayerConfig { } 类CDPlayerConfig通过java代码定义了Spring的装配规则,它并没有显式地声明任何bean,不过使用了@ComponentScan注解,这个注解能够在Spring中启用组件扫描。 如果没有配置的话,@ComponentScan默认会扫描与配置类相同的包。因为CDPlayerConfig类位于soundsystem包中,因此Spring将会默认扫描这个包以及这个包下的所有子包,查找带有@Component注解的类。这样的话就能发现CompactDisc,并且会在Spring中自动为其创建一个bean。 @Configuration表名这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。 注:@ComponentScan注解如果想要扫描其他包可以添加value值,如果想扫描多个基础包可以用用basePackages属性进行配置 @Configuration @ComponentScan(value="soundsystem") public class CDPlayerConfig { } @Configuration @ComponentScan(basePackages={"soundsystem","otherpackage"}) public class CDPlayerConfig { } 上面这个例子中,所设置的基础包是以 String类型表示的,这是可以的,但是这种方法是类型不安全的。如果你重构代码的话,那么所指定的基础包就可能会出错。 除了将包设置成String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所含的类或接口: @Configuration @ComponentScan(basePackageClasses={CompactDisc.class,otherExist.class}) public class CDPlayerConfig { } ### 4.编写测试类 ### 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; /** *@作者:JackHisen(gwd) *@email:1154978352@qq.com *@时间:2017年7月29日 下午7:33:48 *@version 1.0 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc compactDisc; @Test public void cdShoudNotBeNull(){ assertNotNull(compactDisc); } } CDPlayerTest使用了Spring的SpringJunit4ClassRunner,以便在测试开始的时候自动创建Spring的应用上下文。注解@ContextConfiguration会告诉它需要在CDPlayerConfig中加载配置。因为CDPlayerConfig类包含了@ComponentScan,因此最终的应用上下文应该包含CompactDisc bean。 ## 扩展: ## 在上面的应用程序中,所有的对象都是独立的,彼此之间没有任何依赖,就行SgtPeppers bean这样,那么那你所需要的可能就是组件扫描而已。但是,很多对象会依赖其他的对象才能完成任务。这样的话,我们就需要一种方法能够将组件扫描得到的bean和它们的依赖装配在一起,这个时候就需要用到Spring的自动装配了。 简单来说,自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。为了声明要进行自动装配,我们可以借助Spring的@Autowired注解(或者@Inject注解)。 ### (1)创建有依赖的类 ### 例如下面的CDPlayer类,它的构造器上添加了@Autowired注解,这表明当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean。 package soundsystem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** *@作者:JackHisen(gwd) *@email:1154978352@qq.com *@时间:2017年7月30日 下午9:09:43 *@version 1.0 */ @Component public class CDPlayer implements MediaPlayer{ private CompactDisc cd; //当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean //@Auto注解不仅能够用在构造器上还能用在类的任何地方 @Autowired public CDPlayer(CompactDisc cd) { this.cd = cd; } public void play(){ cd.play(); } } 需要注意的是,@Autowired注解可以在类的任何地方。另外如果没有匹配的bean,那么在应用的上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属性设置为false,这个时候Spring会尝试执行自动装配,但是如果没有装配的bean的话,SPring将会让bean处于未装配的状态。但是,把ruquired属性设置为false时,你需要谨慎对待。如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性有可能会出现NullPointerException。 ### (2)测试自动装配 ### package soundsystem; import static org.junit.Assert.*; import org.apache.tomcat.util.security.MD5Encoder; 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; /** *@作者:JackHisen(gwd) *@email:1154978352@qq.com *@时间:2017年7月29日 下午7:33:48 *@version 1.0 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc compactDisc; @Autowired private MediaPlayer player; @Test public void cdShoudNotBeNull(){ assertNotNull(compactDisc); } @Test public void play(){ player.play(); } } ## (二)xml形式的自动装配 ## ### 1.xml组件扫描 ### <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <context:component-scan base-package="soundsystem"/> </beans> ### 2.测试类 ### 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; /** *@作者:JackHisen(gwd) *@email:1154978352@qq.com *@时间:2017年7月29日 下午7:33:48 *@version 1.0 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:applicationContext.xml") public class CDPlayerTest { @Autowired private CompactDisc compactDisc; @Test public void cdShoudNotBeNull(){ assertNotNull(compactDisc); } } 其他均与java代码形式一致。
还没有评论,来说两句吧...