Spring核心之依赖注入【DI】

126 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

哈喽,大家好!我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在掘金上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。 本文主要讲解Spring核心之依赖注入,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎 ❤️点赞👍、收藏⭐、留言💬 ✨✨✨个人主页:JinHuan

依赖注入DI

DI-Dependency Injection,即依赖注入:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件当中。依赖注入的目的并非为软件系统带来更多工能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身业务的逻辑,而不需要关心具体的资源来自何处,由谁实现。

Ioc是一中思想,是一个概念,实现其的方式有很多种。依赖注入就是其中用的较多的一种方式。

Ioc和DI是同一个概念的不同角度的描述。Ioc是一种思想、概念,DI是实现它的一种手段。Spring框架通过使用依赖注入来实现Ioc。

Spring是一个超大工厂。负责创建、管理所有的Java对象,这些Java对象被称为Bean。

Spring容器管理着容器中的bean之间的依赖关系,Spring使用“依赖注入”的方式来管理Bean之间的依赖关系。使用Ioc实现对象之间的的解耦合。

注入分类

bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化是由容器自动完成的,称为注入。

通过set方法(常用)

set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用。

通过构造方法注入

构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。使用构造器设置依赖关系。

自动注入

对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为标签 设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属 性)。根据自动注入判断标准的不同,可以分为两种: byName:根据名称自动注入

当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。

byType: 根据类型自动注入

使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。

DI.xml

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 <!--依赖注入-->
     <bean id="teamDao" class="com.jinhuan.dao.TeamDao"/>
     <!--通过Set注入属性值                                                                                                          -->
     <bean id="teamService" class="com.jinhuan.service.TeamService">
         <property name="teamDao" ref="teamDao"></property>
     </bean>
 ​
     <!--通过构造注入-->
     <bean id="teamService2" class="com.jinhuan.service.TeamService">
         <constructor-arg name="teamDao" ref="teamDao"/>
     </bean>
 ​
     <!--自动注入-->
         <!--按照名称
             autowire  byName
             容器会自动检索teamService3这个实例中所需要的属性值,根据名字teamDao来进行查找并自动注入
         -->
     <bean id="teamService3" class="com.jinhuan.service.TeamService" autowire="byName"/>
         <!--按照类型注入
             autowire  byType
             容器会自动检索teamService3这个实例中所需要的属性值,根据类型来进行查找并自动注入
                                 该类型可以是子类或者其实现类,即 is a 关系
                 注意:只有单一类型的时候会成功,多个同类型会失败报错,因为不知道是注入该类型的那个bean(不唯一 )
         -->
     <bean id="teamService4" class="com.jinhuan.service.TeamService" autowire="byType"/>
 </beans>

TeamDao

 public class TeamDao {
     public void add(){
         System.out.println("Team-----------add()-----------");
     }
 ​
     public TeamDao() {
         System.out.println("TeamDao-------默认构造方法被使用");
     }
 }

TeamService

 package com.jinhuan.service;
 ​
 import com.jinhuan.dao.TeamDao;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 ​
 /**
  * @Author jinhuan
  * @Date 2022/5/9 19:46
  * Description:
  */
 @Service
 public class TeamService {
     private TeamDao teamDao;//new TeamDao();是原来的方法
 ​
     
     public void add(){
         teamDao.add();
     }
 ​
     /**
      * 使用Set注入
      * */
     public void setTeamDao(TeamDao teamDao) {
         this.teamDao = teamDao;
     }
 ​
     public TeamDao getTeamDao() {
         return teamDao;
     }
 ​
     /**
      * 构造注入
      * */
     public TeamService(TeamDao teamDao) {
         this.teamDao = teamDao;
     }
 ​
     public TeamService() {
         System.out.println("TeamService--------无参构造方法被使用");
     }
 ​
 }

Test类

 package com.jinhuan.test;
 ​
 import com.jinhuan.service.TeamService;
 import org.junit.Test;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 ​
 /**
  * @Author jinhuan
  * @Date 2022/5/9 20:51
  * Description:
  */
 public class Test03 {
     @Test
     public void test() {
         ApplicationContext ac = new ClassPathXmlApplicationContext("DI.xml");
         //使用Set注入获取的TeamService对象
         TeamService teamService = (TeamService) ac.getBean("teamService");
         //使用构造注入获取的TeamService对象
         TeamService teamService4 = (TeamService) ac.getBean("teamService2");
         //按照名称自动注入
         TeamService teamService2 = (TeamService) ac.getBean("teamService3");
         //按照类型自动注入
         TeamService teamService3 = (TeamService) ac.getBean("teamService4");
 ​
         teamService.add();
         teamService2.add();
         teamService3.add();
         teamService4.add();
     }
 }
 ​

image-20220703103636379