全注解下的SpringIoc 续1

news2024/11/15 0:16:58

上篇文章介绍了ioc的基本用法和@ComponentScan注解的使用,这篇文章我们来看看依赖注入的部分。
提起依赖注入,想必大家肯定会想到@Autowired注解,的确,它是我们用的最多的一个。
还记得容器的顶级接口BeanFactory 吗,它定义了获取bean的几个方法,主要是基于类型和基于名称来获取bean,而这里即将要介绍的@Autowired注解便是首先基于类型来获取bean的。

下面我们来看个例子,有个人需要让自己的宠物来帮自己做些事情,这里我们先定义人和动物的接口:

public interface Person {
    /**
     * 使用动物服务
     */
    void service();
}

public interface Animal {
    /**
     * 动物的使用方法
     */
    void use();
}

然后分别定义它们的实现类:

@Component
public class DiBusinessPerson implements Person {

    @Autowired
    private Animal cat;

    @Override
    public void service() {
        this.cat.use();
    }
    
@Component
@Slf4j
public class DiCat implements Animal {
    @Override
    public void use() {
        log.warn("猫【{}】是抓老鼠用的。", DiCat.class.getSimpleName());
    }
}

注意:对于DiBusinessPerson 类中的成员变量dog,我们使用了@Autowired注解标记,这样spring容器在创建这个bean时,会自动将其依赖的Animal 注入进来,也就是spring会帮助我们创建Animal 的实例,并将其赋值给dog,完成依赖注入。
然后我们还是定义一个配置类,用来配置扫描规则;

@Configuration
@ComponentScan(basePackages = {"com.zzm.iocdi"})
public class DiAppConfig {

}

最后创建测试类,运行main方法看下效果:

@Slf4j
public class IocDiTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(DiAppConfig.class);
        Person person = context.getBean(DiBusinessPerson.class);
        person.service();
    }
}

在这里插入图片描述
从日志可以看到,cat对象已经被成功注入到DiBusinessPerson对象中,完成了依赖注入。

歧义性问题

但是,如果这个人想要养多只不同种类的宠物时,要怎么办呢?假设现在想再养只狗狗,那么首先,我们需要创建狗狗的类,然后在DiBusinessPerson类中再添加一只狗狗的变量

@Component
@Slf4j
public class DiDog implements Animal {
    @Override
    public void use() {
        log.warn("狗【{}】是看门用的。", DiDog.class.getSimpleName());
    }
}

@Component
public class DiBusinessPerson implements Person {
    @Autowired
    private Animal cat;

    @Autowired
    private Animal dog;

    @Override
    public void service() {
        this.cat.use();
        this.dog.use();
    }

}

再次运行测试类的main方法,可以看到如下日志:
在这里插入图片描述
发现程序报错了,原因是Animal接口存在两个实现类,@Autowired注解根据Animal类型找到了两只动物,它不知道应该要注入哪一个,所以出现了这个错误。
为了解决这个问题,我们首先再回顾一下@Autowired注解的应用机制:

Created with Raphaël 2.3.0 开始 根据类型匹配bean 根据类型是否可以准确匹配到? 注入成功 结束 根据名称匹配bean 根据名称是否可以准确匹配到? 是否可以为空? 抛出异常,注入失败 yes no yes no yes no

因为我们没有特殊设置@Autowired注解的属性,所以会按照它的默认机制,也就是上述流程进行bean的注入,它默认被注入的对象是不能为空的,所以这里就抛出了异常。

方案1

现在,我们来解决这个问题,既然它根据类型匹配到了多个宠物(猫、狗),那么我们让它根据名称可以定位到,修改下DiBusinessPerson类中猫和狗的变量名称,和对应的bean的名称保持一致,如下:

@Component
public class DiBusinessPerson implements Person {
    @Autowired
    private Animal diCat;

    @Autowired
    private Animal diDog;

    @Override
    public void service() {
        this.diCat.use();
        this.diDog.use();
    }

}

然后再次运行程序,可见如下日志,表示已经注入成功了。
在这里插入图片描述
但是,这种写法业界内并不推荐,因为成员变量的名称被限制,怎么都感觉不靠谱,所以下面介绍另外一种方案。

方案2

@Primary注解的使用。
该注解用于修改注入优先级的,它会使得被标记的对象优先注入。
这里我们以猫对象为例,修改代码如下:

@Primary
@Component
@Slf4j
public class DiCat implements Animal {
    @Override
    public void use() {
        log.warn("猫【{}】是抓老鼠用的。", DiCat.class.getSimpleName());
    }
}

@Component
public class DiBusinessPerson implements Person {
    @Autowired
    private Animal cat;

    @Autowired
    private Animal dog;

    @Override
    public void service() {
        this.cat.use();
        this.dog.use();
    }

}

然后再次运行程序,可见如下日志:
在这里插入图片描述
程序没有报错了,注入已经成功了。但是,有没有发现,这两个宠物都变成了猫,我们原先的设想是一只猫、一只狗,现在因为猫对象里面使用了@Primary注解提升了注入优先级,所以@Autowired注解在注入时就会优先选择猫。
很显然,这并不是我们想要的,为了达到目的,这里引出了这个注解,@Qualifier
它的value属性可以让我们指定需要注入的bean名称,从而和@Autowired相互配合,使我们得到正确的结果。
修改代码如下:

@Component
public class DiBusinessPerson implements Person {
    @Autowired
    @Qualifier("diCat")
    private Animal cat;

    @Autowired
    @Qualifier("diDog")
    private Animal dog;

    @Override
    public void service() {
        this.cat.use();
        this.dog.use();
    }

}

然后再次运行程序,可见如下日志:
在这里插入图片描述
可以看到,猫和狗都各司其职了。

带有参数的构造方法类的装配

上面的例子都是基于这些类的构造方法是没有参数的,那么,有参数的构造方法的类要怎么注入呢?让我们一起来看看。。。
修改DiBusinessPerson类的代码,使其包含有参数的构造方法,代码如下:

@Component
public class DiBusinessPerson implements Person {
    @Autowired
    @Qualifier("diCat")
    private Animal cat;

    private Animal dog;
    
	@Autowired(required = false)
    private Animal dog2;

    private Animal cat2;

    public DiBusinessPerson(@Autowired @Qualifier("diDog") Animal dog){
        this.dog = dog;
    }

    @Override
    public void service() {
        this.cat.use();
        this.dog.use();
        this.cat2.use();
    }

    @Autowired
    @Qualifier("diCat")
    public void setAnimal(Animal animal) {
        this.cat2 = animal;
    }
}

可以看到,这里将@Autowired @Qualifier两个注解用来了构造方法的参数和自定义方法上,所以spring在创建DiBusinessPerson 对象调用构造方法时,也会将需要的狗狗实例注入进来。这两个注解也可以用于自定义的方法参数之上,感兴趣的小伙伴可以自行尝试下。
然后我们再次运行main方法,得到如下日志:
在这里插入图片描述
可见是注入成功的。
另外,@Autowired注解默认是必须要匹配到一个值的,不然就会报错,但是我们可以设置其允许为空,如dog2属性的注入。

下次写关于bean的生命周期的,敬请期待。。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/443118.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信开发者工具使用git提交项目至gitee远程仓库(保姆级)

1. 开始 1.1. 点击进入gitee官网 进入主页之后,根据图片右上角点击新建仓库 输入自定义仓库名称, 访问路径点击创建仓库 这里不要点击初始化文件, 复制Git远程仓库路径 打开微信开发者工具,新建项目什么的就不多说了,打开项目,根据图片所示, 点击版本管理弹出窗口, 点击远程…

代码生涯冲常见的的bug.例如layui表格中日期自动生成、eacharts 报表的重复点击事件

1、layui表格中日期不受控制的自动生成&#xff0c;这种情况往往是你设置了日期类型的强转 例 对于这种情况你需要定义templet模板 1、 {field: outtime, title: 离开时间,templet : "#time"} 2、 <script type"text/html" id"time"> …

通过Salesforce考试 (考证) 后,如何在Trailhead上验证和维护证书?

随着Salesforce产品家族的不断壮大&#xff0c;学习者可以考的认证也在不断增多。从十几年前的几个认证&#xff0c;增长到现在的40多个认证。 在获得Salesforce认证之后&#xff0c;除了要将其放在LinkedIn和Trailblazer.me个人资料中&#xff0c;还有一种官方途径可以让其他…

野火STM32电机系列(五)Cubemx配置高级定时器TIM1

鸽了一段时间&#xff0c;放心不会断的哈&#xff0c;目前仅仅是显示屏坏了&#xff0c;不影响后面项目 前文已经配置了GPIO、编码器 本节讲解CubeMX高级定时器TIM1配置带死区的6路互补的PWM 同时配置信号触发后续ADC采集 板子引角的原理图如下 对应的&#xff1a; Motor1…

一文告诉你什么是无代码?无代码开发有什么好处

全球知名IT研究机构曾预测&#xff1a;到2025年&#xff0c;企业机构开发的新应用中&#xff0c;有70&#xff05;将会使用无代码技术&#xff0c;并会使用至少四种低代码或无代码开发工具。甚至有人预言&#xff1a;“代码—低代码—无代码”&#xff0c;将是编程历史上的一种…

2022年中国广义数据智能市场规模为442亿元

数据智能是当前市场上的热点应用。但业界对于数据智能的发展状况&#xff0c;缺乏深入探讨与研究。为了系统梳理中国数据智能行业市场全景&#xff0c;厘清行业发展脉络&#xff0c;为从业者提供有价值的借鉴&#xff0c;海比研究院联合中国软件网、中国软件行业协会应用软件产…

Zabbix“专家坐诊”第188期问答汇总

问题一 Q&#xff1a;zabbix能监控waf日志针对告警么&#xff1f; A&#xff1a;可以通过snmp trap的方式。 Q&#xff1a;snmp trap在zabbix端怎么配置呢&#xff1f;我配置的不生效&#xff0c;zabbix服务器端。 A&#xff1a;trap要先在设备开启&#xff0c;设备有告警会…

绒毛/短毛渲染

文章目录 多层毛发模型123 代码实现cgincshader refer&#xff1a; 腾讯游戏学堂 主要来自这里&#xff0c;感谢讲解&#xff01; 首先说一点&#xff0c;很多文章都把毛发和头发弄混&#xff0c;根本就不是一回事好吧&#xff0c;为了区分&#xff0c;我的两篇文章分别用了长…

数值分析(四) Hermite(埃尔米特)插值法及matlab代码

目录 前言一、Hermite插值1. Hermite定理2. 重节点差商3. 重节点Newton插值4. Hermite 插值公式4.1 三点三次 Hermite插值4.2 两点三次 Hermite插值4.3 2 n 1 2n1 2n1次Hermite插值多项式 二、Hermite插值算法及matlab代码1. 2 n 1 2n1 2n1次Hermite插值matlab代码实现2. 例…

2.1寸黑白TFT电子标签【基站版】

ESL_TFT_2.1_V4 产品参数 产品型号 ESL_TFT_2.1_V4 尺寸(mm) 69.5*35*14.8mm 显示技术 TFT 反射式 显示区域(mm) 23.71(H) * 48.55(V) 分辨率(像素) 250*122 像素尺寸(mm) 0.194*0.194 显示颜色 黑/白 视觉角度 45/45/60/60 工作温度 -20-70℃ 产品重量 …

Mysql第一章 字符集

字符集修改 一 在mysql5.7中输入汉字报错二 修改针对修改后创建的数据库&#xff0c;过去创建的数据库不算三 想要单独修改四 基本的mysql命令五 各级别的字符集 一 在mysql5.7中输入汉字报错 # 在5,7中&#xff0c;默认字符集为latin1,开发人员在数据库设计时&#xff0c;需要…

Python用curve_fit进行多元拟合

文章目录 入门参数多元拟合 入门 scipy.optimize中&#xff0c;curve_fit函数可调用非线性最小二乘法进行函数拟合&#xff0c;例如&#xff0c;现在有一个高斯函数想要被拟合 y a exp ⁡ − ( x − b c ) 2 y a\exp-(\frac{x-b}{c})^2 yaexp−(cx−b​)2 则调用方法如下 …

Zookeeper源码分析——Follower和Leader状态同步源码

Follower和Leader状态同步源码 当选举结束后&#xff0c;每个节点都需要根据自己的角色更新自己的状态。选举出的Leader更新自己状态为 Leader&#xff0c;其他节点更新自己状态为 Follower Leader更新状态入口&#xff1a; leader.lead() Follower更新状态入口&#xff1a; f…

VUE3 学习笔记(九)使用富文本编辑器tinymce最新版

目录 1、安装相关依赖 2、下载中文包 3. 引入皮肤和汉化包 4. 封装组件:在src/components下新建TEditor.vue&#xff0c;并写入以下代码 5. 注册及使用组件 6. Tinymce 版本&#xff08;截至2023-04-18&#xff09; 1、安装相关依赖 npm install tinymce -S npm install ti…

python+vue小型公司人事企业员工培训报名管理系统

该系统主要实现了公告信息管理、个人考勤管理、培训信息管理、员工管理、员工工资管理等主要模块功能。具体功能如下所示&#xff1a; 1. 公告信息管理&#xff1a;查看公告标题、公告类型、公告图片、发布日期等一系列信息。 2. 个人考勤管理&#xff1a;查看考勤名称、员工工…

Springboot整合Quartz定时任务框架(Spring解决方案)

目录 前言 介绍 集成 POM依赖 基础配置 1、配置数据源 2、配置JOB实例与触发器 3、配置SchedulerJobFactory 4、配置SchedulerFactoryBean 业务集成 job编写 接口编写 接口实现 前言 系统现在有定时任务触发业务场景的需求&#xff0c;并且频率及次数不固定&…

【案例教程】FVCOM流域、海洋水环境数值模拟方法及实践技术应用

近年来&#xff0c;随着人类活动产生营养负荷的增加&#xff0c;流域、海洋生态系统面临严重威胁。近岸水质数值模是近岸水环境保护的有效工具&#xff0c;已经应用于近岸水环境污染控制、水质规划管理中。FVCOM在近岸水环境模拟方面具有一定优势&#xff0c;如采用非结构化三角…

王道计组(23版)2_数据的表示和运算

1.数制和编码 十进制转换为二进制&#xff1a; 原码&#xff1a; [0]原0,0000 [-0]原1,0000 -1无法表示 补码&#xff1a; 按位取反&#xff0c;末位加1 [0.0000]补[-0.0000]补0.00000 反码&#xff1a; 按位取反 [0]反0,0000 [-0]反1,1111 移码&#xff1a; 与补码仅符号位…

从前端角度快速理解Transformer

从前端角度快速理解Transformer Transformer的三步曲从前端角度&#xff08;SEO和TDK&#xff09;理解TransformerSEO与TDK一个例子来理解 总结 声明&#xff1a;本文为原创&#xff0c;未经同意请勿转载或爬取&#xff0c;感谢配合&#x1f604; chatGPT今年年初的时候是非常火…

操作系统实验一 并发程序设计

1.实验目的 掌握Linux环境下&#xff0c;多进程之间并发程序设计方法&#xff0c;并通过程序的运行结果来验证分时系统和并发程序设计的优越性。 2.实验要求 熟悉Linux操作系统子进程创建方法以及任务执行时间测量方法 3.实验内容 在单进程&#xff08;单用户、单任务&#xff…