Spring基础篇:通过@Component标注的类注入到其他Bean中

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 通过@Component标注的类注入到其他Bean中

例子

配置Dao操作接口,底层有通过MysqlOracle实现Dao的两种方式;

配置UserService接口和它的实现类UserServiceImpl,在实现类中通过类依赖注入的方式,将对应的底层实现注入,为了解耦的方便,配置注入的名称通过properties文件标注。

目录及代码说明

嫌啰嗦可以跳过这段:目录及代码说明

目录结构

image.png

Dao接口

public interface Dao {
    public String getUserNameById();
}

Dao的Mysql实现类代码

public class MysqlDaoImpl implements Dao {
    @Override
    public String getUserNameById() {
        return "mysql";
    }
}

Dao的Oracle实现类代码

public class OracleDaoImpl implements Dao {
    @Override
    public String getUserNameById() {
        return "oracle";
    }
}

UserService接口

public interface UserService {
    public String getUserNameByID();
}

UserService接口实现类代码

public class UserServiceImpl implements UserService {
    @Override
    public String getUserNameByID() {
        return null;
    }
}

步骤

第一步:需要将交给容器的类,用注解标注

  • MysqlDaoImplOracleDaoImpl两个类上面加上@Component注解
  • UserServiceImpl类上加上@Service注解
说明: @Service是基于 @Component的,它们的作用是一样的,只是作为架构方面来说,@Service能够提醒阅读代码的人,了解这是一个Service类。

第二步:配置配置类

@Configuration
@ComponentScan("juejin.autowrite")
public class AutoWriteConfig {
}

就是扫描配置注解的Bean

第三步:使用@Autowired注解

@Service
public class UserServiceImpl implements UserService {
    private Dao dao;

    @Autowired
    public void setDao(Dao dao) {
        this.dao = dao;
    }

    @Override
    public String getUserNameByID() {
        return dao.getUserNameById();
    }
}

我们的目的是:在ServiceImpl中需要用到Dao的实现,所以通过set方式上添加@Autowired注解,就可以自动将Spring容器中对应的类型注入到该属性中。

第三步:写启动类,启动

public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AutoWriteConfig.class);
        UserServiceImpl bean = ctx.getBean(UserServiceImpl.class);
        String name = bean.getUserNameByID();
        System.out.println(name);
    }
}

不出意外的话,你会得到一条报错信息NoUniqueBeanDefinitionException,这个错误在自动注入时经常出现呢。

原因:

  • Dao有两个实现类MysqlDaoImplOracleDaoImpl
  • 我们在Service中注入的是
    private Dao dao;

    @Autowired
    public void setDao(Dao dao) {
        this.dao = dao;
    }

注意,上面有提到过@Autowired是按照类型注入的,那么Dao现在有两个实现类,Spring容器已经无法分清到底需要哪个了。

解决 NoUniqueBeanDefinitionException 报错

1. 使用@Qualifier配合@Autowired

@Autowired
@Qualifier("mysqlDaoImpl")
public void setDao(Dao dao) {
    this.dao = dao;
}

输出:mysql

解释:这是因为@Qualifier告诉了Spring容器,我需要注入的Bean名称,Spring容器根据id找Bean就不会出现不知道找哪个的问题啦。

2. 使用@Primary注解

在Service中还是老样子

@Autowired
public void setDao(Dao dao) {
    this.dao = dao;
}

我们在Dao实现类OracleDaoImpl上加上@Primary注解

@Component
@Primary
public class OracleDaoImpl implements Dao {
    @Override
    public String getUserNameById() {
        return "oracle";
    }
}

输出:oracle

3.简化方法1,使用@Resource注解

@Resource = @Autowrite + @Qualifier
这个注解将两个注解合体使用啦,所以理解没有那么困难。

现状,硬编码的硬伤

@Autowired
@Qualifier("mysqlDaoImpl")
public void setDao(Dao dao) {
    this.dao = dao;
}

这个mysqlDaoImpl名字我是手动输入的,将它换成使用properties注入,更加灵活

创建properties文件

daoName=mysqlDaoImpl

在配置类中使用@PropertySource

用法见Spring基础篇:利用注解将外部Properties属性注入到Bean中的方法 - 掘金 (juejin.cn)

使用@Resource注解

配置name属性,通过配置的读取的外部文件,注入到name属性中,实现通过配置文件修改底部注入的类。

@Resource(name = "${daoName}")
public void setDao(Dao dao) {
    this.dao = dao;
}
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
6天前
|
Java uml Spring
手写spring第四章-完善bean实例化,自动填充成员属性
手写spring第四章-完善bean实例化,自动填充成员属性
15 0
|
3天前
|
消息中间件 安全 Java
在Spring Bean中,如何通过Java配置类定义Bean?
【4月更文挑战第30天】在Spring Bean中,如何通过Java配置类定义Bean?
11 1
|
5天前
|
前端开发 Java 数据格式
【Spring系列笔记】定义Bean的方式
在Spring Boot应用程序中,定义Bean是非常常见的操作,它是构建应用程序的基础。Spring Boot提供了多种方式来定义Bean,每种方式都有其适用的场景和优势。
20 2
|
6天前
|
XML Java 数据格式
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
6 0
|
6天前
|
XML Java 数据格式
手写spring第六章-实现应用上下文,完成bean的扩展机制
手写spring第六章-实现应用上下文,完成bean的扩展机制
12 0
|
XML JSON Java
Spring component detection logic
Spring component detection logic
Spring component detection logic
|
2月前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
47 0
|
2月前
|
缓存 安全 Java
Spring Boot 面试题及答案整理,最新面试题
Spring Boot 面试题及答案整理,最新面试题
122 0
|
1月前
|
存储 JSON Java
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
29 2
|
2月前
|
前端开发 搜索推荐 Java
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革