目录

  • 依赖注入
    • 未使用依赖注入
    • 使用依赖注入
  • 装配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相关推荐

  1. Spring实战读书笔记 高级装配(1)

    一.条件化装配 1. 当你希望你的bean在特殊条件下才能装配时,比如在声明了特定的bean时,或者配置了特定的环境变量的时候.那么就可以使用 @Conditional注解,可以用在 @Bean注解下 ...

  2. Spring实战之二:装配Bean

    2.1 Spring配置的可选方案 Spring提供了三种装配机制: 在XML中显式配置 在Java中显式配置 隐式的bean发现机制和自动装配 Best Practice:尽可能使用自动配置的机制, ...

  3. Spring实战——通过Java代码装配bean

    上篇说的是无需半行xml配置完成bean的自动化注入.这篇仍然不要任何xml配置,通过Java代码也能达到同样的效果. 这么说,是要把上篇的料拿出来再煮一遍? 当然不是,上篇我们几乎都在用注解的方式如 ...

  4. [Spring实战系列](12)Bean的自动装配

    Spring提供了4种各具特色的自动装配策略: 类型 说明 no 默认方式,Bean的引用必须通过XML文件中的</ref>元素或者ref属性手动设定. byName 把与Bean的属性具 ...

  5. Spring4实战读书笔记

    Spring4实战读书笔记 首先,我们需要明白,为什么我们需要引入Spring,也就是说Spring的好处.个人觉得主要是在于两方面解耦和对bean的管理. 第一部分:Spring核心 共分为四个章节 ...

  6. Go语言实战读书笔记

    2019独角兽企业重金招聘Python工程师标准>>> Go语言实战读书笔记 第二章 通道(channel).映射(map)和切片(slice)是引用类型.引用类型的对象需要使用ma ...

  7. iPhone与iPad开发实战读书笔记

    iPhone开发一些读书笔记 手机应用分类 1.教育工具 2.生活工具 3.社交应用 4.定位工具 5.游戏 6.报纸和杂志的阅读器 7.移动办公应用 8.财经工具 9.手机购物应用 10.风景区相关 ...

  8. 马丁福勒《UML精粹》读书笔记_第四章

    第四章 顺序图 顺序图是一个use case的一种实现.当考察单个use case内部若干对象的行为时,就应使用顺序图. 可参考"高焕堂<嵌入式UML设计>读书笔记_第五章&qu ...

  9. 马丁福勒《UML精粹》读书笔记_第一章

    马丁福勒<UML精粹>读书笔记_第一章 UML的使用场景 必须遵从UML规则吗? 在上述草图.蓝图的场景下,不必过多强调遵从UML规则.因为我们使用UML的目的是为了一个好的设计,所以应将 ...

最新文章

  1. SQL 关于apply的两种形式cross apply 和 outer apply
  2. 操作系统任务执行和任务切换的基本实现原理
  3. dbcc dbreindex server sql_DBCC DBREINDEX重建索引提高SQL Server性能
  4. 实现对现有的aspx请求进行异步队列控制处理
  5. reactor和thread线程_Reactor模型详解:单Reactor多线程与主从Reactor多线程
  6. [DP/单调队列]BZOJ 2059 [Usaco2010 Nov]Buying Feed 购买饲料
  7. c++ array stl_C ++ STL中带有示例的array :: front()函数
  8. leetcode - 617. 合并二叉树
  9. Atitti cto的日常流程与职责attilax总结
  10. 截图贴图取色Snipaste
  11. 超详细的遗传算法(Genetic Algorithm)解析【转】
  12. 2023考研数学冲刺模拟卷资源———以及模拟卷难度评估
  13. Eclipes和Myeclipse插件安装方法
  14. 第三章 添加背景音乐与音频剪辑
  15. 欢迎 收听 海口DJ江林 混音 你的样子 异域风格 为您倾心打造 DJ 江林 reim 短指键盘松哥原创
  16. java 案例:二月天;求月一共有多少天
  17. 盲源分离matlab程序,Ica盲源分离Matlab程序
  18. openwrt 模块编译与opkg应用
  19. 【蓝桥杯单片机】DS1302模块
  20. 华为C8800真机测试如何打开logcat

热门文章

  1. a标签的tagart属性
  2. Bresenham画线算法笔记
  3. 简单实现ProgressBar三色图(带有百分比)
  4. PHPMyWind编辑器支持pdf自动上传
  5. 文档查看器PrizmDoc Viewer v13.13发布:多个修订及更新
  6. 基于ThinkPHP框架的简单的后台管理系统
  7. JAVA WEB 开源CMS系统,可用来二次开发
  8. 腾讯王巨宏:“未来+教育”,以智能技术助力人才培养新模式
  9. 2022年全球天然气分配系统行业分析报告
  10. 三丰三坐标编程基本步骤_蔡司三坐标测量机操作技巧,有蔡司三坐标的工厂都清除清楚吗?...