Spring入门(二):自动化装配bean
Spring从两个角度来实现自动化装配:
- 组件扫描(component scanning):Spring会自动发现应用上下文中需要创建的bean。
- 自动装配(autowiring):Spring会自动满足bean之间的依赖。
为了更形象的解释组件扫描与自动装配,我们举一个音响系统的例子,主要包含以下内容:
- CD接口
- CD接口的一个实现类
- CD播放器
关于CD和CD播放器关系的解释:
如果你不将CD插入(注入)到CD播放器中,那么CD播放器其实是没有太大用处的。所以,可以这样说,
CD播放器依赖于CD才能完成它的使命。
1. 创建可被发现的bean
先创建CD接口CompactDisc:
package chapter02;public interface CompactDisc {void play();
}
然后创建CD接口的一个实现类SgtPeppers:
package chapter02;import org.springframework.stereotype.Component;@Component
public class SgtPeppers implements CompactDisc {@Overridepublic void play() {String title = "Sgt.Pepper's Lonely Hearts Club Band";String artists = "The Beatles";System.out.println("Playing " + title + " By " + artists);}
}
SgtPeppers类与以往类的区别在于使用了@Component
注解。
这个注解表明该类会作为组件类,并告知Spring要为这个类创建bean。
那么如何让Spring发现它并创建bean呢?
这时就需要用到组件扫描,不过,在Spring中,组件扫描默认是不启用的。
因此我们需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。
创建CDPlayerConfig类:
package chapter02;import org.springframework.context.annotation.ComponentScan;@ComponentScan
public class CDPlayerConfig {
}
这个类与以往类的区别是使用了@ComponentScan
注解,这个注解能够让Spring启用组件扫描。
@ComponentScan默认会扫描与配置类相同的包以及这个包下的所有子包,查找带有@Component注解的类。
2. 验证组件扫描
为了验证创建的bean能否被Spring发现,我们创建一个简单的JUnit测试,完成此测试需要导入以下两个jar包:
- hamcrest-core-2.1.jar
- junit-4.12.jar
导入jar包的方式如下:
导入完成后的项目结构图如下所示:
package chapter02;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 {@Autowiredprivate CompactDisc compactDisc;@Testpublic void cdShouldNotBeNull() {assertNotNull(compactDisc);compactDisc.play();}
}
代码简单讲解:
@RunWith(SpringJUnit4ClassRunner.class)
,会在测试开始的时候自动创建Spring的应用上下文。
@ContextConfiguration(classes = CDPlayerConfig.class)
会告诉Spring需要在CDPlayerConfig中加载配置。
字段compactDisc上的@Autowired
注解,会将SgtPeppers bean注入到字段compactDisc上,因为它是接口CompactDisc的实现类并且添加了@Component
注解。
运行测试方法cdShouldNotBeNull,会发现测试通过,compactDisc不为null:
3. 设置bean ID
Spring应用上下文中所有的bean都会给定一个ID,默认情况下,Spring会将类名的第一个字母变为小写,作为该bean的ID。
如上面代码中SgtPeppers bean的ID为sgtPeppers。
有以下两种方式来设置bean ID:
3.1 使用@Component设置bean ID
@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {......
}
3.2 使用@Named设置bean ID
@Named注解不是Spring框架的注解,而是Java 依赖注入规范(Java Dependency Injection)中的注解,因此需要导入jar包:javax.inject-1.jar,导入jar包的方式可以参考 Spring入门(一):创建Spring项目。
import javax.inject.Named;@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {......
}
在Spring项目中建议使用@Component
注解。
4. 设置组件扫描的基础包
按照默认规则 ,@ComponentScan
注解会以配置类所在的包作为基础包(base package)来扫描组件。
但有时候,我们会将配置类放在单独的包中,使其与其他的应用代码区分开来。
这种场景下,默认的基础包就满足不了需求。
@ComponentScan
注解支持传入指定的基础包,有以下几种场景:
4.1 指定要扫描的基础包(单个)
@ComponentScan("chapter02")
public class CDPlayerConfig {
}
或者:
@ComponentScan(basePackages = "chapter02")
public class CDPlayerConfig {
}
4.2 指定要扫描的基础包(多个)
@ComponentScan(basePackages = {"chapter01", "chapter02"})
public class CDPlayerConfig {
}
4.3 指定要扫描的基础包(类型安全)
@ComponentScan(basePackageClasses = {CDPlayer.class})
public class CDPlayerConfig {
}
basePackageClasses也支持指定多个类,指定类所在的包将会作为组件扫描的基础包。
建议使用这种类型安全方式来指定扫描的基础包。
5. 通过为bean添加注解实现自动装配
自动装配是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需要的其他bean。
实现自动装配,需要使用Spring的@Autowired
注解。
@Autowired
一般情况下,有以下3种使用方式:
5.1 使用在构造器上
package chapter02;public interface MediaPlayer {void play();
}
package chapter02;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class CDPlayer implements MediaPlayer {private CompactDisc compactDisc;@Autowiredpublic CDPlayer(CompactDisc compactDisc) {this.compactDisc = compactDisc;}@Overridepublic void play() {compactDisc.play();}
}
5.2 使用在属性的Setter方法上
package chapter02;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class CDPlayer implements MediaPlayer {private CompactDisc compactDisc;@Autowiredpublic void setCompactDisc(CompactDisc compactDisc) {this.compactDisc = compactDisc;}@Overridepublic void play() {compactDisc.play();}
}
5.3 使用在类的任何方法上
package chapter02;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class CDPlayer implements MediaPlayer {private CompactDisc compactDisc;@Autowiredpublic void insertDisc(CompactDisc compactDisc) {this.compactDisc = compactDisc;}@Overridepublic void play() {compactDisc.play();}
}
不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。
假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。
如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。
可以通过设置require属性为false避免该异常出现:
@Autowired(required = false)
public CDPlayer(CompactDisc compactDisc) {this.compactDisc = compactDisc;
}
不过建议谨慎使用,避免未找到bean进行匹配,而且代码没有进行null检查而出现NullPointerException。
如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行自动装配。
@Autowired注解也可以替换成@Inject注解(来源于Java依赖注入规范),同样可以实现自动装配:
package chapter02;import org.springframework.stereotype.Component;
import javax.inject.Inject;@Component
public class CDPlayer implements MediaPlayer {private CompactDisc compactDisc;@Injectpublic CDPlayer(CompactDisc compactDisc) {this.compactDisc = compactDisc;}@Overridepublic void play() {compactDisc.play();}
}
在Spring项目中建议使用@Autowired注解。
6. 验证自动装配
修改CDPlayerTest类代码测试自动装配。
package chapter02;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;import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {@Rulepublic final StandardOutputStreamLog log = new StandardOutputStreamLog();@Autowiredprivate MediaPlayer mediaPlayer;@Autowiredprivate CompactDisc compactDisc;@Testpublic void cdShouldNotBeNull() {assertNotNull(compactDisc);compactDisc.play();}@Testpublic void play() {mediaPlayer.play();assertEquals("Playing Sgt.Pepper's Lonely Hearts Club Band By The Beatles\r\n", log.getLog());}
}
因为代码中使用了StandardOutputStreamLog类,因此需要导入jar包:system-rules-1.16.0.jar,导入jar包的方式可以参考 Spring入门(一):创建Spring项目。
运行测试方法play(),输出内容和预期一致,说明字段mediaPlayer已经被MediaPlayer的实现类CDPlayer bean装配,测试通过,如下所示:
7. 源码及参考
源码地址:https://github.com/zwwhnly/spring-action.git,欢迎下载。
Craig Walls 《Spring实战(第4版)》
8. 最后
欢迎扫码关注微信公众号:「申城异乡人」,定期分享Java技术干货,让我们一起进步。
转载于:https://www.cnblogs.com/zwwhnly/p/10478615.html
Spring入门(二):自动化装配bean相关推荐
- Spring学习系列(二) 自动化装配Bean
一.Spring装配-自动化装配 @Component和@ComponentScan 通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组 ...
- Spring实战01——自动化装配bean
自动装配bean 的四种方式: 首先定义一个类,使用@Configuration 标注类成为配置类,然后有下面四种方式: 1.配置类使用@ComponentScan 注解扫描指定包下的类,默认是扫描同 ...
- Spring实战之二:装配Bean
2.1 Spring配置的可选方案 Spring提供了三种装配机制: 在XML中显式配置 在Java中显式配置 隐式的bean发现机制和自动装配 Best Practice:尽可能使用自动配置的机制, ...
- 第2章—装配Bean—自动化装配Bean
自动化装配Bean 2.1.Spring配置可选方案 装配是依赖注入DI的本质,Spring提供了以下三种注入的装配机制: 在XMl中进行显式配置 在java中进行显式配置 隐式的Bean发现机制 ...
- Spring Bean之JavaConfig自动化装配bean
一.简介: Spring能够进行自动化的装配,它使用两种方式来进行自动化装配: 1.组件扫描: Spring会自动发现应用上下文中所创建的bean 2.自动装配: Spring会自动满 ...
- Spring学习之Spring三种装配机制:(一)自动化装配bean
装配:创建应用组件(对象)之间的协作的行为,这也是Spring依赖注入(DI)的本质. Spring提供了三种装配机制: 隐式的自动装配bean: 通过java代码装配bean(显示): 通XML中装 ...
- 【Core Spring】二、装配beans
在Spring中,对象不负责寻找和创建它们需要的其他对象.创建两个应用对象之间关联的动作是依赖注入的核心功能,通常称为装配. 创建beans和构建它们之间的关系是Spring的责任,但是告诉Sprin ...
- Spring 自动化装配Bean
声明一张cd的接口: public interface CompactDisc {public abstract void play(); } 实现cd接口: @Component("Sgt ...
- Spring学习笔记--自动装配Bean属性
Spring提供了四种类型的自动装配策略: byName – 把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中. byType – 把与Bean的属性具有相同类型 ...
最新文章
- Udacity机器人软件工程师课程笔记(二十八) - 卷积神经网络实例 - Fashion-MNIST数据集
- 从 CALayer 的 Position、AnchorPoint 说起
- swift_001(Swift的注释)
- VS2017文件操作之使用fopen函数总结
- django2.0.6 连接使用redis集群
- 设置计算机的出站和入站规则
- 为JavaOne 2014做好准备!
- 数据库SQL ServerSQL Server教程:详细学习游标
- mysql问题排查_mysql问题排查
- DisGeNet:疾病相关的基因与突变位点数据库
- 安川机器人仿真软件安装
- 测井 时深转换 matlab,时深转换操作步骤.pdf
- Unity 改变下载资源商店中资源默认路径的方法
- bootstrap编写响应式页面
- QQ跳转浏览器php代码,QQ微信域名预防封禁强制跳转至浏览器打开PHP源代码下载...
- 无法找到指定DLL库文件“v8.dIl“中的输出命令“Initializev8”
- 关于runtime error '429'解决方案
- axture动画原型制作_小孩子最喜欢的国产“机甲”动画,90后全看过,00后一个也不知道...
- 软件设计师备考(三)——UML(关系和UML图)
- lingo中@wrap函数的理解
热门文章
- 数码印花为何打印精度太高,成品却越不清晰?
- ISO-8601格式时间转换
- 中英文会计科目对照表
- 错误:Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/db.properties]
- 实验一 网络对抗技术
- 磁盘配额管理disk quotas
- 递归算法——阶乘、斐波那契数列
- import和require
- Testin云测试:联想K900热卖 完美兼容10000款主流App
- 数据驱动的网络入侵检测:最新动向与研究趋势