使用@Autowired、@Qualifier、@Primary注解自动装配组件

news2024/9/25 21:21:31

1.@Autowired、@Qualifier、@Primary注解

1.1.@Autowired注解

@Autowired注解可以对类成员变量、方法和构造函数进行标注,完成自动装配的工作。

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	boolean required() default true;
}

@Autowired注解说明:

  1. @Autowired注解默认是优先按照类型去容器中找对应的组件,若找到则就赋值,相当于是调用了如下这个方法:
    applicationContext.getBean(类名.class);
    
  2. 如果找到多个相同类型的组件,那么是将属性名称作为组件的id,到IOC容器中进行查找,这时就相当于是调用了如下这个方法:
    applicationContext.getBean("组件的id");
    

1.2.@Qualifier注解

@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,那么就需要配合@Qualifier注解来使用了。

@Qualifier注解的源码,如下所示:

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {

	String value() default "";

}

1.3.@Primary注解

在Spring中使用注解时,常常会使用到@Autowired这个注解,它默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口而言,可能会有几种不同的实现类,而在默认只会采取其中一种实现的情况下,就可以使用@Primary注解来标注优先使用哪一个实现类。

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {

}

2.自动装配

Spring组件的自动装配就是Spring利用依赖注入,也就是我们通常所说的DI,完成对IOC容器中各个组件的依赖关系赋值。

3.程序案例

3.1.测试@Autowired注解

3.1.1.测试1

创建BookDao、BookService、BookServiceImpl和BookController

  • BookDao
    package com.tianxia.springannotation.dao;
    
    import org.springframework.stereotype.Repository;
    
    /**
     * BookDao
     * @author liqb
     * @date 2023-04-21 16:37
     **/
    // 名字默认是类名首字母小写
    @Repository
    public class BookDao {
    }
    
  • BookService
    package com.tianxia.springannotation.service;
    
    /**
     * BookService
     * @author liqb
     * @date 2023-04-21 16:38
     **/
    public interface BookService {
    }
    
    
  • BookServiceImpl
    package com.tianxia.springannotation.service.impl;
    
    import com.tianxia.springannotation.dao.BookDao;
    import com.tianxia.springannotation.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * BookServiceImpl
     * @author liqb
     * @date 2023-04-21 16:38
     **/
    @Service
    public class BookServiceImpl implements BookService {
    
        @Autowired
        private BookDao bookDao;
    
        /**
         * 打印方法
         * @author liqb
         * @date 2023-05-06 13:09
         */
        public void print() {
            System.out.println(bookDao);
        }
        
        @Override
        public String toString() {
            return "BookService [bookDao=" + bookDao + "]";
        }
    }
    
  • BookController
    package com.tianxia.springannotation.controller;
    
    import com.tianxia.springannotation.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    
    /**
     * BookController
     * @author liqb
     * @date 2023-04-21 16:39
     **/
    @Controller
    public class BookController {
        
        @Autowired
        private BookService bookService;
    }
    

为了更好的看到效果,在项目的config包下创建MainConfigOfAutowired配置类,如下所示:

package com.tianxia.springannotation.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类
 * @author liqb
 * @date 2023-05-06 13:11
 **/
@Configuration
@ComponentScan({"com.tianxia.springannotation.service", "com.tianxia.springannotation.dao", "com.tianxia.springannotation.controller"})
public class MainConfigOfAutowired {
}

运行测试方法,输出结果如下所示:

/**
 * 测试方法
 * @author liqb
 * @date 2023-05-06 13:14
 */
@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);

    BookService bookService = applicationContext.getBean(BookService.class);
    System.out.println(bookService);
    
    BookDao bookDao = applicationContext.getBean(BookDao.class);
		System.out.println(bookDao);

    applicationContext.close();
}

在这里插入图片描述

BookService类中使用@Autowired注解注入的BookDao对象和直接从IOC容器中获取的BookDao对象是同一个对象

3.1.2.测试2

在Spring容器中存在对多个BookDao对象,那么这时又该如何处理

对BookDao类进行改造,为其加上一个lable字段,并为其赋一个默认值,如下所示。

package com.tianxia.springannotation.dao;

import org.springframework.stereotype.Repository;

/**
 * BookDao
 * @author liqb
 * @date 2023-04-21 16:37
 **/
// 名字默认是类名首字母小写
@Repository
public class BookDao {

    private String lable = "1";

    public String getLable() {
        return lable;
    }

    public void setLable(String lable) {
        this.lable = lable;
    }

    @Override
    public String toString() {
        return "BookDao [lable=" + lable + "]";
    }
}

在MainConfigOfAutowired配置类中注入一个BookDao对象,并且显示指定该对象在IOC容器中的bean的名称为bookDao2,并还为该对象的lable字段赋值为2

package com.tianxia.springannotation.config;

import com.tianxia.springannotation.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类
 * @author liqb
 * @date 2023-05-06 13:11
 **/
@Configuration
@ComponentScan({"com.tianxia.springannotation.service", "com.tianxia.springannotation.dao", "com.tianxia.springannotation.controller"})
public class MainConfigOfAutowired {

    /**
     * 注入bookDao对象
     * @author liqb
     * @date 2023-05-06 13:27
     * @return
     */
    @Bean("bookDao2")
    public BookDao bookDao() {
        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }
}

运行测试方法,输出结果如下所示:

/**
 * 测试方法
 * @author liqb
 * @date 2023-05-06 13:14
 */
@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);

    BookService bookService = applicationContext.getBean(BookService.class);
    System.out.println(bookService);

    applicationContext.close();
}

在这里插入图片描述

结果信息输出了lable=1,说明,@Autowired注解默认是优先按照类型去容器中找对应的组件,找到就赋值;如果找到多个相同类型的组件,那么再将属性的名称作为组件的id,到IOC容器中进行查找

让@Autowired注解装配bookDao2

将BookService类中的bookDao属性的名称全部修改为bookDao2即可,如下所示:

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }
    
    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

运行测试方法,输出结果如下所示:

在这里插入图片描述

结论:@Autowired注解默认是优先按照类型去容器中找对应的组件,找到就赋值;如果找到多个相同类型的组件,那么再将属性的名称作为组件的id,到IOC容器中进行查找。

3.1.3.测试3

@Autowired注解属性required

required=false这个玩意的意思就是说找到就装配,找不到就拉到,就别装配了

require= true,未找到相应的bean对象,Spring就会抛出了异常

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    @Autowired(required = false)
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }

    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

3.2.测试@Qualifier注解

显示指定@Autowired注解装配哪个组件

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    @Qualifier("bookDao")
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }

    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

运行测试方法,输出结果如下所示:

在这里插入图片描述

此时尽管字段的名称为bookDao2,但是使用了@Qualifier注解显示指定了@Autowired注解装配bookDao对象,所以,最终的结果中输出了bookDao对象的信息。

3.3.测试@Primary注解

在Spring中,对同一个接口而言,可能会有几种不同的实现类,而默认只会采取其中一种实现的情况下,就可以使用@Primary注解来标注优先使用哪一个实现类。

在MainConfigOfAutowired配置类的bookDao()方法上添加上@Primary注解,如下所示:

package com.tianxia.springannotation.config;

import com.tianxia.springannotation.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * 配置类
 * @author liqb
 * @date 2023-05-06 13:11
 **/
@Configuration
@ComponentScan({"com.tianxia.springannotation.service", "com.tianxia.springannotation.dao", "com.tianxia.springannotation.controller"})
public class MainConfigOfAutowired {

    /**
     * 注入bookDao对象
     * @author liqb
     * @date 2023-05-06 13:27
     * @return
     */
    @Primary
    @Bean("bookDao2")
    public BookDao bookDao() {
        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }
}

注释掉BookService类中bookDao字段上的@Qualifier注解

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    // @Qualifier("bookDao")
    @Autowired(required = false)
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }

    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

运行测试方法,输出结果如下所示:
在这里插入图片描述

此时lable的值为2,这说明装配了MainConfigOfAutowired配置类中注入的bookDao2

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

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

相关文章

hexo stellar主题添加运行时间-利用不蒜子

在网站的页脚想添加博客运行的时间以及,查了一下资料,根据下面的这个博主的代码进行了修改。 打造一个舒服的写作环境(Hexo) 下面我们开始修改: stellar/layout/_partial/main/footer.ejs 找到//footer的 这一段 // …

基于logback 实现springboot的日志配置

目录 一、前言 二、使用详解 2.1、打印到文件中 2.2、打印级别控制 2.3、logback 详细配置 2.4、logback 配置文件的组成 2.4.1、<root>标签 2.4.2、<contextName>标签 2.4.3、<property>标签 2.4.4、<appender>标签 2.4.5、<logger&g…

Mysql索引(2):索引结构

1 概述 MySQL的索引是在存储引擎层实现的&#xff0c;不同的存储引擎有不同的索引结构&#xff0c;主要包含以下几种&#xff1a; 索引结构描述BTree索最常见的索引类型&#xff0c;大部分引擎都支持 B 树索引 Hash索引 底层数据结构是用哈希表实现的, 只有精确匹配索引列的…

ShardingProxy分库分表实战

目录 ShardingProxy简述 快速使用 ShardingProxy部署 ShardingProxy使用 ShardingProxy的服务治理 Shardingproxy的其他功能 ShardingProxy的SPI扩展 ShardingSphere总结 ShardingProxy简述 ShardingProxy的功能同样是分库分表&#xff0c;但是他是一个独立部署的服务…

林曦讲座 | 关于“无用之美”的11个闪光

林曦老师的新书《无用之美》即将和大家见面啦~    究竟什么是“无用之美”呢&#xff1f;早在2013年&#xff0c;林曦老师就曾在“一席”做过一场关于“无用之美”的分享。2019年又在微软做过一次《中国人的闲情逸致——无用之美》的演讲。这次将两次演讲的内容精华整理出来…

【LeetCode】14. 最长公共前缀

1. 问题 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 “”。 示例 1 输入&#xff1a;strs [“flower”,“flow”,“flight”] 输出&#xff1a;“fl” 示例 2 输入&#xff1a;strs [“dog”,“racecar”,“car”] 输出…

虹科动态 | 2023成都国际工业博览会精彩瞬间回顾

2023成都国际工业博览会&#xff08;CDIIF&#xff09;于中国国际西部博览城圆满落下帷幕。本届成都工博会紧紧围绕“工业引领&#xff0c;赋能产业新发展”主题&#xff0c;聚焦工业自动化、数控机床与金属加工、机器人、新一代信息技术与应用、工业互联网、新材料、节能与工业…

在VMware上对于CentOS虚拟机的克隆

一. 执行克隆操作 对已有的虚拟机右键&#xff0c;找到克隆操作&#xff0c;选择完整克隆&#xff0c;之后修改一下虚拟机名称和位置&#xff0c;点击完成即可。 克隆之后还需要修改一些东西&#xff0c;以防止运行期间的 ip 浮动之类的问题。 二. 修改配置 先关闭原来的虚拟…

三菱GOT2000人机界面设置用户报警和系统报警弹出报警显示的具体方法

三菱GOT2000人机界面设置用户报警和系统报警弹出报警显示的具体方法 弹出报警显示功能可以将用户报警、系统报警直接显示再各窗口上起到提示作用,在不切换窗口的情况下直观的提示客户当前设备报警信息。 该功能可以实现将当前发生的用户和系统报警,显示在各个窗口的指定位置(…

Springboot整合Jasypt实战

Springboot整合Jasypt实战 引入依赖 <dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.5</version> </dependency>配置jasypt # 配置jasypt相关信息…

PowerShell系列(一):PowerShell介绍和cmd命令行的区别

目录 1、cmd命令行窗口有哪些缺点呢&#xff1f; 2、PowerShell的产生 3、PowerShell优点 4、PowerShell使用场景 什么是Windows系统的命令行环境&#xff0c;之前我们在使用XP、Win7系统的时候&#xff0c;用的最多的就是微软官方自带的cmd命令窗口了&#xff0c;我们通过敲命…

面向万物智联的应用框架的思考和探索(下)

原文&#xff1a;面向万物智联的应用框架的思考和探索&#xff08;下&#xff09;&#xff0c;点击链接查看更多技术内容。 应用框架&#xff0c;是操作系统连接开发者生态&#xff0c;实现用户体验的关键基础设施。其中&#xff0c;开发效率和运行体验是永恒的诉求&#xff0c…

导轨式传感器差分信号转换模块隔离放大变送器0-±10mV/0-±20mV转0-10V/4-20mA

概述&#xff1a; DIN11 IPO 压力应变桥信号处理系列隔离放大器是一种将差分输入信号隔离放大、转换成按比例输出的直流信号导轨安装变送模块。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等行业。此系列模块内部嵌入了一个高效微功率的电源&#xff0c;向输…

Android+opencv实时人脸与人眼检测案例分享

软件版本&#xff1a; Android Studio Electric Eel 2022.1.1 Patch 2 https://sourceforge.net/projects/opencvlibrary/files/4.5.0/opencv-4.5.0-android-sdk.zip/download 创建工程并导入opencv sdk: 导入opencv sdk: File->New->Import Module 添加工程依赖&am…

如何利用超融合提升制造业开发测试效率 [附用户案例]

进入数字时代&#xff0c;越来越多的制造业企业正在通过自主研发的方式加速应用创新。由于研发效率在很大程度上取决于支持开发测试的服务器、存储等 IT 基础设施的性能&#xff0c;企业需要简单、灵活、高性能的 IT 基础架构&#xff0c;来为研发团队提供资源共享与快速交付支…

Windows微信可以上网但是浏览器却用不了网络如何解决

1、清除DNS缓存。这个主要用于某些网站打不开的情形。 首先同时按WINDOWSR键&#xff0c;在弹出窗口输入CMD&#xff0c;然后回车。 在弹出的命令提示符中输入ipconfig /flushdns&#xff0c;然后回车。 2、重置winsock目录&#xff0c;在命令提示符中输入netsh winsock reset&…

go读request.Body内容踩坑记

go读request.Body内容踩坑记 踩坑代码如下&#xff0c;当时是想获取body传过来的json func demo(c *httpserver.Context) {type ReqData struct {Id int json:"id" validate:"required" schema:"id"Title string json:"…

【LeetCode】-66. 加一

1. 题目 66. 加一 给定一个由 整数 组成的 非空 数组所表示的非负整数&#xff0c;在该数的基础上加一。 最高位数字存放在数组的首位&#xff0c; 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外&#xff0c;这个整数不会以零开头。 2. 示例 输入&#xff1a;dig…

【Python】【进阶篇】23、Django模板变量精讲

目录 23、Django模板变量精讲1. 模板变量1) 变量的命名规范2&#xff09;模板的变量语法3) 模板传参语法格式 23、Django模板变量精讲 在上一节《Django 模板加载与响应》中我们详细讲述了 模板与视图函数如何进行配合使用&#xff0c;同时我们介绍了加载与响应模板的两种方式…

【c语言】字符串输出方式 | API仿真

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ …