Spring Boot2.x-05Spring Boot基础-使用注解完成依赖注入

简介: Spring Boot2.x-05Spring Boot基础-使用注解完成依赖注入

概述


Spring Boot2.x-04Spring Boot基础-使用注解装配bean 中讲了如何将Bean装载到IoC容器中,这里我们说下Bean之间的依赖关系,当然了还是基于注解的方式。


xml的方式去描述Bean之间的依赖关系,请参考以前的博客


Spring-bean之间的关系


Spring-基于注解的配置[02自动装载bean]


@Autowired注解


举个例子: Manager可以安排Engineer去根据Engineer的类型做不同的工作


20181026225517700.png

接口Engineer的接口方法是coding

package com.artisan.springbootmaster.di.intf;
public interface Engineer {
    void coding();
}


假设有个Java程序猿,实现Engineer接口

package com.artisan.springbootmaster.di.intf.impl;
import com.artisan.springbootmaster.di.intf.Engineer;
import org.springframework.stereotype.Service;
@Service
public class JavaEnginerr implements Engineer {
    @Override
    public void coding() {
        System.out.println("Java Engineer works");
    }
}


我们在实现类JavaEnginerr 上使用@Service注解,使其成为一个受Spring容器管理的bean。


接下来,我们来看下Manager类

package com.artisan.springbootmaster.di;
import com.artisan.springbootmaster.di.intf.Engineer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Manager {
    @Autowired
    Engineer engineer;
    public void arrange(){
        engineer.coding();
    }
}


可以通过arrange方法安排engineer工作。 这里Engineer 通过@Autowired让IoC容器自动注入进来。


接着我们使用Java类的方式来初始化IoC容器,通过@Configuration标注其是一个配置类 ,通过ComponetScan来扫描基包下面的标注了注解的类,使其成为受Spring IoC容器托管的bean,方便注入

package com.artisan.springbootmaster.di;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.artisan.springbootmaster.*")
public class Config {
}

最后,加载Java类的配置,主要是依靠 AnnotationConfigApplicationContext,启动容器获取bean,并调用对应的方法

package com.artisan.springbootmaster.di;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class DITest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
        Manager manager =  applicationContext.getBean(Manager.class);
        manager.arrange();
    }
}

运行

23:04:08.018 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'manager'
Java Engineer works



@Autowired会根据属性的类型( by type )找到对应的 Bean 进行注入。

20181026230641492.png


通过结果可以知道,通过注解@Autowired 成功的将JavaEngierr注入到了Manager实例中。


@Autowired的匹配原则

上面这个例子中@Autowired的用法很简单,我们继续来看下@Autowired

当然了,Engineer可能有多个,比如又来了个AndroidEngineer

package com.artisan.springbootmaster.di.intf.impl;
import com.artisan.springbootmaster.di.intf.Engineer;
import org.springframework.stereotype.Service;
@Service
public class AndroidEngineer implements Engineer {
    @Override
    public void coding() {
        System.out.println("Android Engineer works");
    }
}


这是IDEA中可以看到,有提示报错了


20181026231058728.png

让我们继续运行下DITest,抛出了异常

No qualifying bean of type 'com.artisan.springbootmaster.di.intf.Engineer' available: exp


意思很明显,@Autowired根据类型来匹配Engineer,却发现有2个bean都是Engineer类型 ,这下子Spring不知道注入哪个了。


@Autowired的匹配原则:根据类型找到对应的 Bean,如果对应类型的 Bean 不是唯一 的,那么会继续根据其属性名称和 Bean 的名称进行匹配。如果匹配上,就会使用该 Bean,如果还无法匹配,就会抛出异常。


所以根据上面的原则,比较挫的一个办法(这里只是说可以这么改,但是肯定不推荐这么改)


既然是两个,那我就让bean的名字一样呗


方法一:Manager中的Engineer engineer保持不变,给这两个Engineer中的任意一个标注@Service(value "engineer"),指定其bean的名字为engineer,这样根据name就匹配上了,同样不会抛出异常。测试通过。

方法二:Manager中的Engineer engineer改为这两个bean的任意一个名字,@Service标注的实现类Bean的名字为默认第一个字母小写其余保持不变,这样name也能匹配上,同样不会抛出异常。测试通过。


20181026233544816.png


结果


20181026233556556.png


这里只是举例验证下Spring @Autowired的匹配规则,实际工作中并不推荐这么改。。。。


@Autowired的 required 属性


@Autowired 是一个默认必须找到对应 Bean 的注解,如果不能确定其标注属性一定会存在并且允许这个被标注的属性为 null , 那么你可以配置@Autowired 属性 required 为 false.


@Autowired既可以标注在属性上,也可以标注在方法上

@Autowired(required = false)


使用@Primary 和@Qualifier消除@Autowired的歧义


上面通过修改name,使其name保持一致的方式消除了歧义,可以正常的注入,不过并不推荐。


@Primary 不推荐使用


也可以使用@Primary,当然了,也不推荐这么干。 因为另外一个类也可以标注@Primary,Spring又无法知道注入哪个了。


注解@Primary是修改优先权的注解,像上面的两个例子,有2个beanandroidEngineer,javaEnginerr, 如果我们仅在JavaEnginerr这个类上标注@Primary,意思是告诉Spring IoC 容器 , 当发现有多个同样类型的 Bean ,请优先使用标注了@Primary的这个bean进行注入。


20181026233442153.png

结果:


20181026233500132.png


@Qualifier推荐使用


@Qualifier的value属性定义bean的名,该名称将会和@Autowired 组合在一起,通过类型和名称一起找到 Bean。Spring IoC容器中Bean 名称是唯一的标识,通过这个就可以消除歧义了


20181026233749921.png

结果


20181026233800153.png

即使 JavaEnginerr标注了@Primary,但是由于使用了@Qualifier,注入的依然是androidEngineer.


在构造函数/方法中使用@Autowired

上面的例子,我们是在属性上使用的@Autowired.


如果使构造函数呢?

我们改造下Manager

package com.artisan.springbootmaster.di;
import com.artisan.springbootmaster.di.intf.Engineer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Manager {
    Engineer engineer;
    public void arrange(){
        engineer.coding();
    }
    public Manager(@Autowired @Qualifier("javaEnginerr") Engineer engineer){
        this.engineer = engineer;
    }
}


  • 取消标注在属性上的注解
  • 在构造函数上增加注解,使用方法一样。
  • 如果仅有一个类型的Bean, @Qualifier就没有必要加上了。

运行


20181026235138112.png


相关文章
|
2月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
501 128
|
1月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
1月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
1月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
343 2
|
2月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
287 12
|
4月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
867 0
|
1月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
269 3
|
5月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
609 0
|
1月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
795 2
|
8月前
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
390 0