前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Boot简明教程--依赖注入的三种方式

Spring Boot简明教程--依赖注入的三种方式

作者头像
听城
发布2021-01-21 18:58:24
9.5K0
发布2021-01-21 18:58:24
举报
文章被收录于专栏:杂七杂八

官方文档5.3.3:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependencies

准备工作

  • 初始化一个SpringBoot项目
  • 创建pojo包,包下创建Zhangsan、Lisi两个实体类
  • 创建controller包,创建HelloController类
代码语言:javascript
复制
// Zhangsan 
@Component
public class Zhangsan {
    public void say(){
        System.out.println("say hello,i am zhangsan");
    }
}
// Lisi 
@Component
public class Lisi {
    public void say(){
        System.out.println("say hello,i am lisi");
    }
}
// HelloController
@RestController
public class HelloController {
    @GetMapping("/hello")
    public String getHello(){
        return "hello world;";
    }
}

可以看到Zhangsan 、Lisi两个类上都打上了@Component注解,该注解将某个类声明为一个Spring的bean, 然后将其加入到Spring容器中,这是实现注入的前提。(Service、Controller等注解实现注入同样依赖于Component注解)

注入方式

Bean的注入通常使用@Autowired注解,该注解用于bean的field、setter方法以及构造方法上,显式地声明依赖。 在最新的文档中注入方式有两大类:

  • 基于构造函数的依赖注入(推荐使用)
  • 基于setter的依赖注入

但是通常认为还有一种是基于成员变量的依赖注入(spring framerwork 4.0后不推荐使用)

成员变量注入

代码语言:javascript
复制
public class HelloController {
    @Autowired //idea会有一个黄色的波浪线提示Field injection is not recommended(不再推荐使用字段注入)
    private Lisi lisi;
    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}

构造函数注入

  • 方式一
代码语言:javascript
复制
public class HelloController {

    private Lisi lisi;
    @Autowired //这里的Autowired可以加也可以不加,但是建议加上
    public HelloController(Lisi lisi){
        this.lisi = lisi;
    }
    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}
  • 方式二 该方法利用lombok的注解@RequiredArgsConstructor实现构造器注入,需要注意的是要注入的属性需要加上final修饰
代码语言:javascript
复制
@RequiredArgsConstructor
@RestController
public class HelloController {
//    @Autowired
    private final Lisi lisi;


    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}

setter注入

代码语言:javascript
复制
public class HelloController {
//    @Autowired
    private Lisi lisi;
    @Autowired
    public void setLisi(Lisi lisi) {
        this.lisi = lisi;
    }

    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}

拓展 autowired注入形式

首先改造一下我们的项目,将Zhangsan和Lisi两个类继承于Person接口(需要新建),看看运行效果

代码语言:javascript
复制
//person
public interface Person {
    void say();
}
//zhangsan lisi
public class Lisi implements Person{
    public void say(){
        System.out.println("say hello,i am lisi");
    }
}
//hellocontroller
@RequiredArgsConstructor
@RestController
public class HelloController {
    private final Person zhangsan;
    @GetMapping("/hello")
    public String getHello(){
        zhangsan.say();
        return "hello world;";
    }
}
  • 情景一,变量声明为Person person,且只有zhangsan实现了Person接口,则控制台输出say hello,i am zhangsan
  • 情景二,变量声明为Person person,zhangsan和lisi同时实现了Person接口,则运行程序报错constructor in com.example.controller.HelloController required a single bean, but 2 were found:
  • 情景三,变量声明为Person lisi,控制台输出say hello,i am lisi
  • 情景四,变量声明为Person zhangsan,控制台输出say hello,i am zhangsan

上面四个情景展现了Spring中Autowired的两种方式

  • byType,默认的注入方式,与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。
  • byName,与Bean的属性具有相同名字的其他Bean自动装配到Bean的对应属性中

装配方式总结:

  • 找不到任何一个bean报错
  • 一个会直接注入
  • 找到多个,不一定会报错,会按照字段名注入,如果没有同名字的bean则报错

技巧:使用@Qualifier @Qualifier注解是和@Autowired一起使用的。使用此注解可以让你对注入的过程有更多的控制。@Qualifier可以被用在单个构造器或者方法的参数上。当上下文有几个相同类型的bean, 使用@Autowired则无法区分要绑定的bean,此时可以使用@Qualifier来指定名称。

代码语言:javascript
复制
//say hello,i am zhangsan
@RestController
public class HelloController {
    @Qualifier("zhangsan")
    @Autowired
    private Person person;
    @GetMapping("/hello")
    public String getHello(){
        person.say();
        return "hello world;";
    }
}
代码语言:javascript
复制
@RequiredArgsConstructor
@RestController
public class HelloController {
    @Qualifier("zhangsan")
    private final Person person;
    @GetMapping("/hello")
    public String getHello(){
        person.say();
        return "hello world;";
    }
}

如果你想同时使用RequiredArgsConstructor和Qualifier,仅仅写成下面这样还是不行的,需要在项目根目录下新建 lombok.config并写入

代码语言:javascript
复制
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备工作
  • 注入方式
    • 成员变量注入
      • 构造函数注入
        • setter注入
        • 拓展 autowired注入形式
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档