美文网首页java
Spring Boot简明教程--依赖注入的三种方式

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

作者: 听城 | 来源:发表于2021-01-20 18:01 被阅读0次

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

    准备工作

    • 初始化一个SpringBoot项目
    • 创建pojo包,包下创建Zhangsan、Lisi两个实体类
    • 创建controller包,创建HelloController类
    // 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后不推荐使用)

    成员变量注入

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

    构造函数注入

    • 方式一
    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修饰
    @RequiredArgsConstructor
    @RestController
    public class HelloController {
    //    @Autowired
        private final Lisi lisi;
    
    
        @GetMapping("/hello")
        public String getHello(){
            lisi.say();
            return "hello world;";
        }
    }
    

    setter注入

    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接口(需要新建),看看运行效果

    //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来指定名称。

    //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;";
        }
    }
    
    @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并写入

    lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
    

    相关文章

      网友评论

        本文标题:Spring Boot简明教程--依赖注入的三种方式

        本文链接:https://www.haomeiwen.com/subject/hslqzktx.html