【JavaEE进阶】 依赖注⼊DI详解

简介: 【JavaEE进阶】 依赖注⼊DI详解


🌴什么是依赖注入

依赖注⼊是⼀个过程,是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源,⽽资源指的就是对象.

简单来说,就是把对象取出来放到某个类的属性中.

在⼀些⽂章中,依赖注⼊也被称之为"对象注⼊",“属性装配”,具体含义需要结合⽂章的上下⽂来理解

🎄依赖注入的三种方法

关于依赖注⼊,Spring也给我们提供了三种⽅式:

  1. 属性注⼊(Field Injection)
  2. 构造⽅法注⼊(Constructor Injection)
  3. Setter注⼊(Setter Injection)

🚩属性注⼊(Field Injection)

属性注⼊是使⽤ @Autowired 实现的。

比如我们将StudentService类注⼊到StudentController类中.

StudentService.java代码如下:

@Service
public class StudentService {
    public void run() {
        System.out.println("StudentService启动");
    }
}

StudentController.java代码如下:

@RestController
public class StudentController {
    @Autowired
    private StudentService studentService;
    public void run() {
      System.out.println("StudentController启动");
        studentService.run();
    }
}

获取StudentController中的run方法

@SpringBootApplication
public class SpringMvcApplication {
    public static void main(String[] args) {
        //获取spring上下文
        ApplicationContext context = SpringApplication.run(SpringMvcApplication.class, args);
        //从spring中获取对象
        StudentController studentController = context.getBean("studentController",StudentController.class);
        //使用spring对象
        studentController.run();
    }
}

启动项目,结果如下:

🚩构造⽅法注⼊

构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所⽰:

@RestController
public class StudentController {
    private StudentService studentService;
    public StudentController() {
    }
    
    @Autowired
    public StudentController(StudentService studentService) {
        this.studentService = studentService;
    }
    public void run() {
        System.out.println("StudentController启动");
        studentService.run();
    }
}

结果展示:

注意事项:

  • 如果类只有⼀个构造⽅法,那么@Autowired注解可以省略;如果类中有多个构造⽅法,那么需要添加上@Autowired来明确指定到底使⽤哪个构造⽅法
  • 如果存在多个构造方法,还没有写注解的话,就会出现以下问题

🚩Setter注⼊

Setter注⼊和属性的Setter⽅法实现类似,只不过在设置set⽅法的时候需要加上@Autowired注解

@RestController
public class StudentController {
    private StudentService studentService;
    @Autowired
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }
    public void run() {
        System.out.println("StudentController启动");
        studentService.run();
    }
}

🚩三种注⼊的优缺点

属性注⼊:

  • 优点:
  • 简洁,使⽤⽅便;
  • 缺点:
  • 只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指针异常)
  • 不能注⼊⼀个Final修饰的属性

构造函数注⼊(Spring 4.X推荐):

  • 优点:
  • 可以注⼊final修饰的属性
  • 注⼊的对象不会被修改
  • 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法是在类加载阶段就会执⾏的⽅法.
  • 通⽤性好,构造⽅法是JDK⽀持的,所以更换任何框架,他都是适⽤的
  • 缺点:
  • 注⼊多个对象时,代码会⽐较繁琐

Setter注⼊(Spring3.X推荐):

  • 优点:
  • ⽅便在类实例之后,重新对该对象进⾏配置或者注⼊
  • 缺点:
  • 不能注⼊⼀个Final修饰的属性
  • 注⼊对象可能会被改变,因为setter⽅法可能会被多次调⽤,就有被修改的⻛险.

🌳@Autowired存在的问题

当同⼀类型存在多个bean时,在使⽤@Autowired就会存在问题

比如我们有以下bean。

BeanFiguation.java代码如下:

@Configuration
public class BeanFiguation {
    @Bean
    public Student student1() {
        Student student = new Student();
        student.setId(11);
        student.setName("遇事");
        student.setAge(11);
        return student;
    }
    @Bean
    public Student student2() {
        Student student = new Student();
        student.setId(22);
        student.setName("问春风乄");
        student.setAge(22);
        return student;
    }
}

StudentController.java代码如下:

@RestController
public class StudentController {
    @Autowired
    private Student student;
    public void run() {
        System.out.println(student);
    }
}

当我们进行启动时:

报错的原因是,⾮唯⼀的 Bean 对象

🌲解决@Autowired存在的问题

为了解决上述问题,Spring提供了以下4种解决⽅案:

  • bean对象名称与属性名相匹配
  • @Primary
  • @Qualifier
  • @Resource

第一种:bean对象名称与属性名相匹配

第二种:使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现.

第三种:使⽤@Qualifier注解:指定当前要注⼊的bean对象。在@Qualifier的value属性中,指定注⼊的bean的名称。

  • @Qualifier注解不能单独使⽤,必须配合@Autowired使⽤

第四种:使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。

🍃@Autowird与@Resource的区别

  • @Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解
  • @Autowired默认是按照类型注⼊,⽽@Resource是按照名称注⼊.相⽐于@Autowired来说,@Resource⽀持更多的参数设置,例如:name设置,根据名称获取Bean。

⭕总结

关于《【JavaEE进阶】 依赖注⼊DI详解》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

相关文章
|
NoSQL Java 关系型数据库
基于springboot的人力资源管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目。
基于springboot的人力资源管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目。
|
2月前
|
SQL Java 数据库连接
MyBatis-Plus快速入门:从安装到第一个Demo
本文将带你从零开始,快速入门 MyBatis-Plus。我们将首先介绍如何安装和配置 MyBatis-Plus,然后通过一个简单的示例演示如何使用它进行数据操作。无论你是 MyBatis 的新手还是希望提升开发效率的老手,本文都将为你提供清晰的指导和实用的技巧。
531 0
MyBatis-Plus快速入门:从安装到第一个Demo
|
8月前
|
XML Java 数据库
【二十三】springboot整合activiti7(1)实战演示篇
【二十三】springboot整合activiti7(1)实战演示篇
327 0
|
8月前
|
安全 Java Maven
【JavaEE进阶】 SpringBoot的创建与简单使用
【JavaEE进阶】 SpringBoot的创建与简单使用
|
8月前
|
Java 数据库 Spring
Springboot项目中VO包的含义
Springboot项目中VO包的含义
333 0
|
XML 前端开发 Java
一个基础的SpringBoot项目该包含哪些?
建立一个全新的项目,或者把旧的庞大的项目,进行拆分成多个项目。在建立新的项目中,经常需要做一些重复的工作,比如说拷贝一下常用的工具类,通用代码等等。所以就可以做一个基础的项目方便使用,在经历新项目的时候,直接在基础项目上进行简单配置就可以开发业务代码了。
一个基础的SpringBoot项目该包含哪些?
|
运维 安全 Java
SpringBoot实战(十四):Spring Boot Admin 集成安全模块
SpringBoot实战(十四):Spring Boot Admin 集成安全模块
248 0
|
人工智能 Java
SpringBoot实战(一):使用Lombok简化你的代码
SpringBoot实战(一):使用Lombok简化你的代码
100 0
|
Java API 开发工具
SpringBoot3基础用法
SpringBoot3基础用法SpringBoot3基础案例:环境搭建,入门案例,日志组件,全局异常处理,工程打包,服务启动关闭;
257 0
|
Java Maven
SpringBoot2学习(一):第一个项目
SpringBoot2学习(一):第一个项目
139 0
SpringBoot2学习(一):第一个项目