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

news/2024/10/30 15:29:58/

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 {@Autowiredprivate BookDao bookDao;/*** 打印方法* @author liqb* @date 2023-05-06 13:09*/public void print() {System.out.println(bookDao);}@Overridepublic 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 {@Autowiredprivate 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;}@Overridepublic 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 {@Autowiredprivate BookDao bookDao2;/*** 打印方法* @author liqb* @date 2023-05-06 13:09*/public void print() {System.out.println(bookDao2);}@Overridepublic 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);}@Overridepublic 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);}@Overridepublic 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);}@Overridepublic String toString() {return "BookService [bookDao=" + bookDao2 + "]";}
}

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

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


http://www.ppmy.cn/news/60385.html

相关文章

计算卸载论文阅读01-理论梳理

标题:When Learning Joins Edge: Real-time Proportional Computation Offloading via Deep Reinforcement Learning 会议:ICPADS 2019 一、梳理 问题:在任务进行卸载时,往往忽略了任务的特定的卸载比例。 模型:针…

Zero系列三部曲:Zero、Zero-Offload、Zero-Infinity

Zero系列三部曲:Zero、Zero-Offload、Zero-Infinity ZeroIntroductionZero DP流程图详解 Zero-R Zero-OffloadZero- Infinityreference Zero Introduction 以数据并行为例,在训练的时候,首先把模型参数在每个GPU上复制一份,然后…

【微信小程序开发】【SpringBoot】解决真机调试中无法向后台请求数据的问题

前言 最近做了一个微信小程序SpringBoot的一个项目,在编译器中用localhost请求后台可以实现,但是在手机上进行真机调试就无法正确的从后台请求数据,问题已经解决,下面是我的一点经验 获取本机的ip地址(ipv4&#xff09…

一个简单程序JSP+Mysql/ServletAPI+MySQL(servlet获取请求的json数据)

一个简单程序包括两种请求方式 1、JSP+Mysql(JSP获取sql语句对数据库进行查询) 2、ServletAPI+MySQL(servlet获取请求的json数据中的sql语句对数据库进行查询并响应返回) 1. 创建项目 使用 IDEA 创建一个 Maven 项目. 1.1、File -> New Project Name:javaservlet6 Lo…

简单有趣的轻量级网络 Efficientnet(网络结构详解+详细注释代码+核心思想讲解)——pytorch实现

这期博客我们来学习一下Efficientnet网络,属于NAS系列中最优秀的轻量级网络之一,通过NAS搜索的方式确定最佳的网络结构。之前的神经网络的宽度深度,输入图像的分辨率,是怎么获得的呢,说白了就是经验,研究人员通过无数的设计经验获得的,但是网络的发展不可能一直通过经验…

flask+opencv+实时滤镜(原图、黑白、怀旧、素描)

简介:滤镜,主要是用来实现图像的各种特殊效果。图像滤镜用于改变图像的视觉效果,使其具有特定的风格。下面是这三种滤镜的详细说明: 1、黑白(Grayscale):黑白滤镜将彩色图像转换为灰度图像&…

python相对路径与绝对路径

9.1 Python 绝对路径与相对路径 - 知乎 (zhihu.com) 目录 1. 绝对路径 1.1 概念 1.2 用绝对路径打开文件 1.2 相对路径 1.3 python路径表示的斜杠问题 1. 绝对路径 1.1 概念 绝对路径 指完整的描述文件位置的路径。绝对路径就是文件或文件夹在硬盘上的完整路径。 在 Win…

稳定投资思考(三)

沪深300的复合收益率平均值为 7.78% 沪深300指数长期投资回报率分析 作者有以下几点总结: 沪深300指数从2005年至今每个滚动3年期年复合收益率平均值为7.78%,同时波动率为16%,存在高波动的特点。在任意一个月份买入沪深300并且持有3年&#…