《Spring实战》读书笔记_装配bean
目录
- 依赖注入
- 未使用依赖注入
- 使用依赖注入
- 装配bean
- 自动装配
- 自动扫描
- 自动装配
- 用法
- 原理
- 通过Java代码装配Bean
- 通过XML装配Bean(省略)
- 自动装配的歧义性
- 演示歧义性
- 演示一:实现
- 演示二:继承
- 解决歧义性
- 标示首选的bean
- 限定自动装配的bean
依赖注入
未使用依赖注入
- 这个骑士只能使用剑,不能使用其他武器
- 需要使用其他武器时,只能创建另一个骑士类
- 无法进行单元测试
public class Knight implements Solider{private class Weapon weapon;public Knight() {weapon = new Sword();}public void executeTask() {weapon.attack();}
}
使用依赖注入
- 骑士使用的武器从外部获取,骑士没有与任何特定的武器发生耦合
- 骑士在执行任务的时候可以灵活地使用各种武器
- 可以轻松地进行单元测试,只需要传入一个mock weapon即可
public class Knight implements Solider {private class Weapon weapon;public Knight(Weapon weapon) {this.weapon = weapon;}public void executeTask() {weapon.attack();}
}
装配bean
自动装配
自动扫描
- 定义一个CD接口
// CD
public interface CompactDisc {void play();
}
- @component注解表明该类会作为组件类,并告知Spring要为这个类创建bean,所以没有必要显式的配置SgtPeppersBean
- @Component注解创建的bean的默认ID是类名开头字母小写,也就是sgtPeppers
- 可以自定义beanID,用法:@Component(“beanID”)
@component
public class SgtPeppers implements CompactDisc {public void play() { System.out.println("I'm sgtPeppers");}
}
- 组件扫描默认不启用,我们需要显式配置一下启用组件扫描
- 创建一个配置类,使用@ComponentScan注解
- 配置类会扫描所在包以及子包下所有带有@Component注解的类,并为这些类创建一个bean
- 如果你想将配置类单独放在一个包里面,默认的基础包机制失效,可以手动指定扫描的包,给该注解的basePackages传递想要扫描的包名即可
- basePackageClasses传入具体class对象,会扫描这些类所在的包,可以避免上面的String(String是类型不安全的,写代码容易出bug)
- 问题:SpringBoot是如何开启组件扫描的呢?
// 方式一
@Configuration
@ComponentScan
public class CDPlayerConfig {}// 方式二
@Configuration
@ComponentScan(basePackages={"soundsystem", "video"})
public class CDPlayerConfig {}// 方式三
@Configuration
@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
public class CDPlayerConfig {}
自动装配
用法
- 使用@Autowired注解来实现自动装配
- @Autowired可以用在任意方法之上,比如构造器方法,setter方法或者普通方法
- 自动装配也能用在属性上
// 构造函数
@Autowired
public CDPlayer(CompactDisc cd) {this.cd = cd;
}
// setter方法
@Autowired
public void setCompactDisc(CompactDisc cd) {this.cd = cd;
}
// 普通方法
@Autowired
public void insertDisc(CompactDisc cd) {this.cd = cd;
}
原理
- 不管是什么方法,Spring都会尝试满足方法参数上所声明的依赖
- @Autowired先按类型查找bean
- 如果找不到则报错,可以声明required=false,这样找不到时,Spring会让这个bean处于未装配状态,容易报空指针异常
- 如果找到多个bean,需要借助其他注解来解决自动装配中的歧义性
通过Java代码装配Bean
- 使用场景:将第三方库的组件装配到你的应用中时,你是没办法在它的类上添加@Component和@Autowired注解的
- 声明简单的bean,如下:
- @Configuration注解表明这是一个配置类
- @Bean会告诉Spring该方法会返回一个对象,该对象要注册为Spring容器中的bean
- 默认情况下beanID与带有@Bean注解的方法名时一样的,也可以用@Bean注解中的name属性指定一个不同的beanID
@Configuration
public class CDPlayerConfig{@Beanpublic CompactDisc sgtPeppers() {return new SgtPeppers();}
}
- 声明复杂的Bean:CDPlayer,CDPlayer依赖sgtPeppers
- 方式一:因为sgtPeppers()方法上添加了@Bean,Spring会拦截所有对它的调用,并确保直接返回该方法所创建的Bean,这种方式的限制是sgtPeppers()方法和cdPlayer()方法必须放在同一个配置类中
- 方式二:当Spring调用cdPlayer()方法创建一个bean时,它会自动装配一个CompactDisc,这种方式的好处是CompactDisc这个bean如何被注入到Spring的没有限制
- 方式三:使用setter方法注入,可以看到使用带有@Bean注解的方法注入bean时,可以采用任何的java代码来创建bean,方法参数中需要的bean,Spring都会自动传递进来
@Configuration
public class CDPlayerConfig{@Beanpublic CompactDisc sgtPeppers() {return new SgtPeppers();}//方式一@Beanpublic CDPlayer cdPlayer() {return new CDPlayer(sgtPeppers());}//方式二@Beanpublic CDPlayer cdPlayer(CompactDisc compactDisc) {return new CDPlayer(compactDisc);}// 方式三@Beanpublic CDPlayer cdPlayer(CompactDisc compactDisc) {CDPlayer cdPlayer = new CDPlayer();cdPlayer.setCompactDisc(compactDisc);return cdPlayer;}
}
通过XML装配Bean(省略)
自动装配的歧义性
演示歧义性
演示一:实现
- 自动装配bean时,容器中如果找到多个类型相同的bean会阻碍Spring的自动装配,代码如下:
public interface Dessert {}
@Component
public class Cookies implements Dessert {}
@Component
public class Cake implements Dessert {}
@Component
public class IceCream implements Dessert {}
- 依赖注入
- 方式一:注入的Dessert类型的Bean在容器中可以找到三个:Cookies, IceCream, Cake,自动装配失败
- 方式二:如果把注入的类型改成Dessert的子类,自动装配成功
@Component
public class Kitchen {private Dessert dessert;// 方式一@Autowiredpublic void dessert(Dessert dessert) {this.dessert = dessert;}// 方式二public void dessert(Cake dessert) {this.dessert = dessert;}
}
演示二:继承
- 把实现改成继承,方式一的注入依然报错;方式二的注入依然成功
- 如果在父类中也加上@Component
- 上述方式一自动装配成功
- 但是,通过ApplicationContext.getBean(Dessert.class)方法获取bean报错,提示有四个相同类型的bean:Dessert,Cookies,Cake和IceCream
// 演示二
@Component
public class Dessert {}
@Component
public class Cookies extends Dessert {}
@Component
public class Cake extends Dessert {}
@Component
public class IceCream extends Dessert {}
解决歧义性
标示首选的bean
- 有效配置
- @Primary能够与@Component组合用在组件扫描的bean上
- @Primary也能够与@Bean组合用在java配置的bean声明中
- 在xml配置中,<
bean
>标签有一个primary属性用来指定首选的bean,设置为true即可
- 无效配置
- 在多个bean上配置了@Primary
限定自动装配的bean
- @Primary只是标示了一个优先的可选方案,当优先可选方案失效(同上),装配依旧失败
- @Qualifier(“beanId”),默认的限定符是beanId
- @Component默认beanId是类名小写,也可指定beanId:@Component(“beanId”)
- @Bean默认beanId是方法名小写,也可指定beanId:@Bean(“beanId”)
- @Qualifier可以为bean自定义限定符,这样在重构代码(修改类名)的时候,就不会报错
// 注入bean时声明限定符
@Component
@Qualifier("cold")
public class IceCream implements Dessert {}
// 或者:
@Bean
@Qualifier("cold")
pubic Dessert iceCream() {return new IceCream();
}
// 装配bean时指定限定符
@Autowired
@Qualifier("cold")
public void setDessert(Dessert dessert) {this.dessert = dessert;
}
《Spring实战》读书笔记_装配bean相关推荐
- Spring实战读书笔记 高级装配(1)
一.条件化装配 1. 当你希望你的bean在特殊条件下才能装配时,比如在声明了特定的bean时,或者配置了特定的环境变量的时候.那么就可以使用 @Conditional注解,可以用在 @Bean注解下 ...
- Spring实战之二:装配Bean
2.1 Spring配置的可选方案 Spring提供了三种装配机制: 在XML中显式配置 在Java中显式配置 隐式的bean发现机制和自动装配 Best Practice:尽可能使用自动配置的机制, ...
- Spring实战——通过Java代码装配bean
上篇说的是无需半行xml配置完成bean的自动化注入.这篇仍然不要任何xml配置,通过Java代码也能达到同样的效果. 这么说,是要把上篇的料拿出来再煮一遍? 当然不是,上篇我们几乎都在用注解的方式如 ...
- [Spring实战系列](12)Bean的自动装配
Spring提供了4种各具特色的自动装配策略: 类型 说明 no 默认方式,Bean的引用必须通过XML文件中的</ref>元素或者ref属性手动设定. byName 把与Bean的属性具 ...
- Spring4实战读书笔记
Spring4实战读书笔记 首先,我们需要明白,为什么我们需要引入Spring,也就是说Spring的好处.个人觉得主要是在于两方面解耦和对bean的管理. 第一部分:Spring核心 共分为四个章节 ...
- Go语言实战读书笔记
2019独角兽企业重金招聘Python工程师标准>>> Go语言实战读书笔记 第二章 通道(channel).映射(map)和切片(slice)是引用类型.引用类型的对象需要使用ma ...
- iPhone与iPad开发实战读书笔记
iPhone开发一些读书笔记 手机应用分类 1.教育工具 2.生活工具 3.社交应用 4.定位工具 5.游戏 6.报纸和杂志的阅读器 7.移动办公应用 8.财经工具 9.手机购物应用 10.风景区相关 ...
- 马丁福勒《UML精粹》读书笔记_第四章
第四章 顺序图 顺序图是一个use case的一种实现.当考察单个use case内部若干对象的行为时,就应使用顺序图. 可参考"高焕堂<嵌入式UML设计>读书笔记_第五章&qu ...
- 马丁福勒《UML精粹》读书笔记_第一章
马丁福勒<UML精粹>读书笔记_第一章 UML的使用场景 必须遵从UML规则吗? 在上述草图.蓝图的场景下,不必过多强调遵从UML规则.因为我们使用UML的目的是为了一个好的设计,所以应将 ...
最新文章
- SQL 关于apply的两种形式cross apply 和 outer apply
- 操作系统任务执行和任务切换的基本实现原理
- dbcc dbreindex server sql_DBCC DBREINDEX重建索引提高SQL Server性能
- 实现对现有的aspx请求进行异步队列控制处理
- reactor和thread线程_Reactor模型详解:单Reactor多线程与主从Reactor多线程
- [DP/单调队列]BZOJ 2059 [Usaco2010 Nov]Buying Feed 购买饲料
- c++ array stl_C ++ STL中带有示例的array :: front()函数
- leetcode - 617. 合并二叉树
- Atitti cto的日常流程与职责attilax总结
- 截图贴图取色Snipaste
- 超详细的遗传算法(Genetic Algorithm)解析【转】
- 2023考研数学冲刺模拟卷资源———以及模拟卷难度评估
- Eclipes和Myeclipse插件安装方法
- 第三章 添加背景音乐与音频剪辑
- 欢迎 收听 海口DJ江林 混音 你的样子 异域风格 为您倾心打造 DJ 江林 reim 短指键盘松哥原创
- java 案例:二月天;求月一共有多少天
- 盲源分离matlab程序,Ica盲源分离Matlab程序
- openwrt 模块编译与opkg应用
- 【蓝桥杯单片机】DS1302模块
- 华为C8800真机测试如何打开logcat
热门文章
- a标签的tagart属性
- Bresenham画线算法笔记
- 简单实现ProgressBar三色图(带有百分比)
- PHPMyWind编辑器支持pdf自动上传
- 文档查看器PrizmDoc Viewer v13.13发布:多个修订及更新
- 基于ThinkPHP框架的简单的后台管理系统
- JAVA WEB 开源CMS系统,可用来二次开发
- 腾讯王巨宏:“未来+教育”,以智能技术助力人才培养新模式
- 2022年全球天然气分配系统行业分析报告
- 三丰三坐标编程基本步骤_蔡司三坐标测量机操作技巧,有蔡司三坐标的工厂都清除清楚吗?...