spring注入bean的几种策略模式
上篇文章Spring IOC的核心机制:实例化与注入我们提到在有多个实现类的情况下,spring是如何选择特定的bean将其注入到代码片段中,我们讨论了按照名称注入和使用@Qualifier 注解输入的两种方式,本篇文章将结合之前提到的和spring的其他注入方式一起进行讨论。
本文主题
我们将讨论在一个接口或者抽象类在具有多个实现类的情况下,有多少种策略能够让我们在特定的代码片段中注入想要的bean。
按照名称
定义一个Skill借口,他描述了英雄具备哪些技能,现在有两个英雄的实现类Diana和Irelia,通过component注解将其标注为bean,在容器启动的时候会将他们加载到容器中。
现在有一个BannerController要使用Diana这个bean
@RestController
public class BannerController {
@Autowired
private Skill diana;
@RequestMapping(value = "/v2/banner", method = {RequestMethod.GET})
public String test() {
diana.r();
return "Hello SpringBoot";
}
}
private Skill diana;这里将成员变量的名字写成Diana这个bean的名字,容器就会选择Diana这个注入,这就叫做按照名称注入。spring会给每个bean设置默认到的名字也可以自定义,大家自行查找资料了解即可。
@Qualifier 注解
还是上文的例子,如果成员变量名不写成bean的名称,是其他的名字,比如按照常规的写法会写成
private Skill skill;这个时候就可以使用@Qualifier 注解,
@RestController
public class BannerController {
@Autowired
@Qualifier("diana")
private Skill skill;
@RequestMapping(value = "/v2/banner", method = {RequestMethod.GET})
public String test() {
skill.r();
return "Hello SpringBoot";
}
有选择的注入一个bean,注释掉某个bean上的@Component
如果我们确定要使用哪个bean,那可以把其他的注释掉
//@Component
public class Irelia implements Skill {
public Irelia() {
System.out.println("Hello, Irelia");
}
public void q(){
System.out.println("Irelia Q");
}
public void w(){
System.out.println("Irelia W");
}
public void e(){
System.out.println("Irelia E");
}
public void r(){
System.out.println("Irelia R");
}
}
让Skill的实现类只有一个,自然就不要再操心注入哪个了,就只会注入存在于容器当中的惟一的那一个了。
使用@Primary提高bean的优先级
还可以使用@Primary注解提高我们想让注入bean的优先级,那spring在扫描到相同类型的bean的时候,就会看谁的优先级高,谁高谁注入
@Component
@Primary
public class Diana implements Skill {
private String skillName = "Diana R";
public Diana() {
System.out.println("I am Diana");
}
public void q(){
System.out.println("Diana Q");
}
public void w(){
System.out.println("Diana W");
}
public void e(){
System.out.println("Diana E");
}
public void r(){
System.out.println(this.skillName);
}
}
然后启动启动程序,访问路由,就会看到下面的输出:

说明确实是注入了Diana这个bean。
阶段总结
上面的实现方式看起来都能实现按照所需注入特定的bean,但是有个问题,当发生变化的时候,这里的变化可能是英雄名变了,新增英雄或者要替换其他英雄,都需要去手动改代码,有些情况下可能还不只改一处,还是比较繁琐,并不方便。那有没有一种方式可以通过配置文件的形式来指定要注入的bean,当变化发生,只需要改配置,那岂不是很方便很灵活很开心。
条件注解
条件注解顾名思义,就是按照条件决定注入哪一个bean,所以要想使用条件注解,就得先写一个条件。
spring为我们提供了特定的方式来实现自己的条件:@Conditional注解+Condition接口,spring的这种方式的原理是把符合条件的bean加加载到容器中,不合的不加载,那这样在注入的时候就不会有多个相同类型的bean存在了,自然也就注入成功了。
定义一个类实现Condition接口
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class HeroCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
实现Condition接口必须实现它的matches方法,我们先来解释一下这个方法的入参和返回值,
ConditionContext是一个接口,定义了他支持那些操作
public interface ConditionContext {
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
Environment getEnvironment();
ResourceLoader getResourceLoader();
ClassLoader getClassLoader();
}
其中的getEnvironment方法会返回Environment对象,他里面会记录当前应用所有的环境信息,可以通过这个对象获取到我们的配置信息。
返回值是Boolean类型的,哪个bean的条件匹配成功,就会把这个bean注入到代码片段中去。我们来具体实现一下。
public class HeroCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String name = context.getEnvironment().getProperty("hero.condition");
System.out.println(name);
if ("diana".equalsIgnoreCase(name)){
return true;
}else if ("irelia".equalsIgnoreCase(name)){
return true;
}
return false;
}
}
@Configuration
public class HeroConfiguration {
@Bean
@Conditional(HeroCondition.class)
public Skill diana(){
return new Diana();
}
@Bean
@Conditional(HeroCondition.class)
public Skill irelia(){
return new Irelia();
}
}
通过以上的方式,就可以完成一个简单的条件注解,但是这种需求其实spring boot早已经帮我们实现了,提供了一些注解可以使用,下篇文章我们看看使用spring boot的内置注解,如何来解决我们的问题。
博客地址:https://www.immortalp.com/
欢迎大家去 我的博客 瞅瞅,里面有更多关于测试实战的内容哦!!
spring注入bean的几种策略模式的更多相关文章
- spring 注入bean的两种方式
我们都知道,使用spring框架时,不用再使用new来实例化对象了,直接可以通过spring容器来注入即可. 而注入bean有两种方式: 一种是通过XML来配置的,分别有属性注入.构造函数注入和工厂方 ...
- spring注入bean的三种方法
在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. 在第一种利用bean config file(spring xml)方式中 ...
- spring注入bean的五种方式
1.属性注入 2.构造方法注入 3.静态工厂注入 package com.voole.factorybeans; import com.voole.beans.TestBean; public cla ...
- Spring获取bean的几种方式
工作中需要对一个原本加载属性文件的工具类修改成对数据库的操作当然,ado层已经写好,但是需要从Spring中获取bean,然而,工具类并没有交给Spring来管理,所以需要通过方法获取所需要的bean ...
- spring中bean的五种作用域?Spring中的bean是线程安全的吗?
spring中bean的五种作用域 当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...
- spring创建bean的三种方式
spring创建bean的三种方式: 1通过构造方法创建bean(最常用) 1.1 spring默认会通过无参构造方法来创建bean,如果xml文件是这样配置,则实体类中必须要有无参构造方法,无参构造 ...
- Spring中bean的四种注入方式
一.前言 最近在复习Spring的相关内容,这篇博客就来记录一下Spring为bean的属性注入值的四种方式.这篇博客主要讲解在xml文件中,如何为bean的属性注入值,最后也会简单提一下使用注解 ...
- Spring三 Bean的三种创建方式
创建Bean的三种方式在大多数情况下,Spring容器直接通过new关键字调用构造器来创建Bean实例,而class属性指定Bean实例的实现类,但这不是实例化Bean的唯一方法.实际上,Spring ...
- aop代理方式引起的spring注入bean(实现类)与获取bean(实现类)出错
描述: 现象一 :A 为 接口,AImpl 为 A 的实现类,且 AImpl 受 aop 扫描,且 aop 无特殊配置 此时若:Spring 中 注入 AImpl 类型的bean,获取一样 ...
随机推荐
- 一、VMware Workstation 15中文破解版 下载与安装(附密钥)
下载地址: 下载地址VMware Workstation Pro 15.5.0 Build 14665864https://download3.vmware.com/software/wkst/fil ...
- Spring Boot 和 Spring Cloud 应用内存如何管理?
在整体应用架构中,非生产环境情况下,一般 1GB 或者 2GB 的 RAM 就足够了.如果我们将这个应用程序划分为 20 或 30 个独立的微服务,那么很难期望 RAM 仍将保持在 1GB 或 2GB ...
- Hadoop学习笔记(1)-Hadoop在Ubuntu的安装和使用
由于小编在本学期有一门课程需要学习hadoop,需要在ubuntu的linux系统下搭建Hadoop环境,在这个过程中遇到一些问题,写下这篇博客来记录这个过程,并把分享给大家. Hadoop的安装方式 ...
- Alpha-release 总结
因组员一周来事情较多,因此博客更新停滞了一个星期.这周我们已经开始了第二个release的相关工作,首先先对上一个release的工作进行简短总结. 团队在上个星期进行了alpha-release版本 ...
- Windows Pains poj 2585
Boudreaux likes to multitask, especially when it comes to using his computer. Never satisfied with j ...
- PHP 将字符串转换为字符集格式UTF8/GB2312/GBK 函数iconv()
iconv()介绍 iconv函数可以将一种已知的字符集文件转换成另一种已知的字符集文件 iconv('要转化的格式',‘转化后的格式’,‘转化的数据’); 但是转化是经常出错,一般需要在转成的编码 ...
- 解决利用hibernate连接mysql时无法插入汉字的问题
1.先修改mysql数据库的配置文件my.ini,此文件放在mysql安装文件的根目录下.找到default-character-set属性,并将其值更改为utf8(不是utf-8),将default ...
- python安装pil库,操作流程以及安装中出现的问题。
0.用管理员方式打开cmd窗口. 1.跳转到python对应目录 比我: ***或者直接在该路径下输入cmd直接跳转.**** 例如: 直接回车搞定!! 2.输入 pip install pillow ...
- 高性能的JavaScript,这是一个高级程序员必备的技能
不知道大家有没有看过高性能JavaScript,这个书是一本好书,推荐有JavaScript的基础的同学可以看一看这本书. 下面是我根据这本书整理出来的知识: 1.将经常使用的对象成员.数组项.和域外 ...
- 1、flink介绍,反压原理
一.flink介绍 Apache Flink是一个分布式大数据处理引擎,可对有界数据流和无界数据流进行有状态计算. 可部署在各种集群环境,对各种大小的数据规模进行快速计算. 1.1.有界数据流和无界 ...