广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >如何理解IoC的依赖注入
  • 621
分享到

如何理解IoC的依赖注入

2024-04-02 19:04:59 621人浏览 独家记忆
摘要

这篇文章主要讲解了“如何理解ioc的依赖注入”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解ioC的依赖注入”吧! 一、注解驱动IoCxml

这篇文章主要讲解了“如何理解ioc的依赖注入”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解ioC的依赖注入”吧!

 一、注解驱动IoC

xml驱动的IoC容器使用的是ClassPathXmlApplicationContext读取xml内bean信息

注解驱动的IoC容器使用的是AnnotationConfigApplicationContext读取Java类中的bean信息

1. AnnotationConfigApplicationContext 的注册使用

相比于xml文件作为驱动, 注解驱动需要指明配置类 一个配置类可以理解为"相当于"一个xml 配置类只需要在类上标注注解  @Configuration

@Configuration public class DemoConfiguration { }

在xml中声明bean的方式

在配置类中使用的是@Bean注解

<bean id="person" class="com.huodd.bean.Person"></bean>

说明: 向IoC容器注册一个类型为Persion,id为Person的Bean

方法名表示的是bean的id 返回值表示的是注册的bean的类型

@Bean注解也可以显示的声明bean的id  如 @Bean("person1")

@Bean public Person person() {     return new Person(); }

2. 注解IoC容器的初始化

public class AnnotationConfigApplication {     public static void main(String[] args) {         ApplicationContext ctx = new AnnotationConfigApplicationContext(DemoConfiguration.class);         Person person = ctx.getBean(Person.class);         System.out.println(person);     } }

运行后Person控制台打印结果

com.huodd.bean.Person@55536d9e

3. 组件的注册和扫描

上述初始化时 我们在使用AnnotationConfigApplicationContext时传递了参数 Class...  componentClasses

翻看AnnotationConfigApplicationContext的构造方法可以发现还可以传递参数的参数类型还有 String...  basePackages

这里就涉及到组件的注册和扫描

  • 这里可以思考一个问题, 如果我们要注册的组件特别多, 那进行编写这些@Bean的时候代码工作量也会特别多,这时候该如何解决呢?

spring 给我们提供了几个注解,可以帮助我们快速注册需要的组件, 这些注解被称为模式注解(stereotype annotations)

@Component

@Component可以说是所有组件注册的根源 在类上标注 @Component 代表该类被注册到IoC容器中作为一个Bean

@Component public class Person { }

如果未指定 Bean 的名称 默认规则是 "类名称首字母小写" 上面的bean名称默认会是 person

如果要自定义bean的名称 可以在@Component声明value的值即可 如

@Component("person1") public class Person { }

在xml中相当于

<bean id="person1" class="com.huodd.bean.Person"/>

@ComponentScan

这个时候 如果我们直接运行启动类 获取Person的bean对象,会报错NoSuchBeanDefinitionException 这是为什么呢?

因为我们只是声明了组件,而后直接启动了IoC容器,这样容器是感知不到有@Component存在的,

解决方案1:

我们需要在写配置类时再额外标注一个新的注解@ComponentScan

目的是告诉IoC容器 我要扫描哪个包下面的带有@Component注解的类

@Configuration @ComponentScan("com.huodd.bean") public class DemoComponentScanConfiguration { }

: 如果不指定扫描路径, 则默认扫描本类所在包及所有子包下带有@Component的组件

启动类代码如下:

public class AnnotationConfigApplication {     public static void main(String[] args) {         ApplicationContext ctx = new AnnotationConfigApplicationContext(DemoComponentScanConfiguration.class);         Person person = ctx.getBean(Person.class);         System.out.println(person);     } }

解决方案2:

这里也可以不写@ComponentScan  而直接在AnnotationConfigApplicationContext方法参数内传入String类型的包扫描路径 代码如下

public class AnnotationConfigApplication {     public static void main(String[] args) {         ApplicationContext ctx = new AnnotationConfigApplicationContext("com.huodd.bean");         Person person = ctx.getBean(Person.class);         System.out.println(person);     } }

PS: 组件扫描并非是注解驱动IoC所特有的, 其实在xml驱动的IoC模式下 同样可以启用组件扫描, 只需要在xml中声明一个标签即可

<context:component-scan base-package="com.huodd.bean"/>

这里需要注意下: 如需要扫描多个路径,需要写多个标签 也就是 一个标签只能声明一个根包

组件注册的补充

SpringFramework 提供了在进行web开发三层架构时的扩展注解: 分别为 @Controller、 @Service 、@Repository  小伙伴有没有很熟悉?

分别代表 表现层、业务层、持久层 这三个注解的作用与 @Component完全一样 扒开源码我们可以看到 底层在这三个注解类上又添加了  @Component

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Service { }

这样 我们在进行符合三层架构的开发时 对于相应的如 ServiceImpl等 就可以直接标注 @Service 等注解了

@Configuration

@Configuration 底层也有标注@Component

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { ... }

由此可以说明,配置类不是向我们所想的那样,只是单纯的做一个配置而已, 它也会被视为 bean,也被注册到IoC容器里面

4. 注解驱动与xml驱动互相引用

4.1 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"        xmlns:context="http://www.springframework.org/schema/context"        xsi:schemaLocation="http://www.springframework.org/schema/beans         https://www.springframework.org/schema/beans/spring-beans.xsd          http://www.springframework.org/schema/context          https://www.springframework.org/schema/context/spring-context.xsd">      <!-- 开启注解配置 -->     <context:annotation-config />     <!-- 注册配置类 -->     <bean class="com.huodd.config.AnnotationConfiGConfiguration"/> </beans>

4.2 注解引用XMl

@Configuration @ImportResource("classpath:annotation/demo-beans.xml") public class ImportXmlAnnotationConfiguration {  }

二、IoC的依赖注入

1.Setter属性注入

创建对象 将属性值set进去 之后返回对象

@Bean public Person person() {     Person person = new Person();     person.setId(1);     person.setName("PoXing");     person.setAge(18);     return person; }

xml中的setter注入

<bean id="person" class="com.huodd.bean.Person">     <property name="id" value="1"/>     <property name="name" value="PoXing"/>     <property name="age" value="18"/> </bean>

2. 构造器注入

使用构造器注入,需要在bean本身添加有参构造方法, 如在Person中添加有参构造方法如下

public Person(Integer id, String name, Integer age) {         this.id = id;         this.name = name;         this.age = age; }

注解驱动中,我们创建bean的时候注入属性时 就需要同时指定参数值

@Bean public Person person() {     return new Person(1, "PoXing", 18); }

xml驱动中如下

<bean id="person" class="com.huodd.bean.Person">     <!--    index: 表示构造器的参数索引   value: 表示对应的参数值  -->     <constructor-arg index="0" value="1"/>     <constructor-arg index="1" value="PoXing"/>     <constructor-arg index="2" value="18"/> </bean>

3. 注解式属性注入

这里先说明一下,为何会有注解式属性值注入. 细心的小伙伴可能会发现 上面我们谈到的 Setter属性注入、构造器注入 好像在只能是在使用  @Bean注解的时候时候使用, 但是 如果是通过标注  @Component注解的组件呢(像前面我们的Person类中标注了@Component注解),怎么给它设定属性值, 该节主要就是说一下这部分

@Component 下的属性注入

这里我们使用Dog类做为演示(这里我悄悄的添加了@Component注解 自己尝试的小伙伴要注意哦 否则会报错的)

@Component public class Dog {     private Integer id;     private String name;     private Integer age;     ... 省略 Getter、Setter    ... 省略 toString  }

这里要实现注解式属性注入,可以直接在要注入的字段上标注 @Value注解 如

@Value("1") private Integer id;  @Value("wangcai") private String name;  @Value("3") private Integer age;

启动类代码如下

public class DiApplication {     public static void main(String[] args) {         ApplicationContext ctx = new AnnotationConfigApplicationContext("com.huodd.bean");         Dog dog = ctx.getBean(Dog.class);         System.out.println(dog);     } }

控制台打印结果

Dog{id=1, name='wangcai', age=3}

外部配置文件(@PropertySource)

这里主要是解决上面的@Value中注入 我们把属性值直接固定写死了,如果要修改 还要去Java代码中去修改,很不符合开发规范,

SpringFramework为我们扩展了新的注解@PropertySource 主要用来导入外部配置文件

1.这里我们创建一个 dog.properties

dog.id=1 dog.name=wangcai dog.age=3

2.引入配置文件

@PropertySource("classpath:di/dog.properties") @ComponentScan("com.huodd.bean") @Configuration public class DemoComponentScanConfiguration { }

3.Dog类中属性注入 这里@Value需要配合占位符 来获取properties配置文件中的内容

@Value("${dog.id}") private Integer id;  @Value("${dog.name}") private String name;  @Value("${dog.age}") private Integer age;

4.修改一下启动类

public class DiApplication {     public static void main(String[] args) {         ApplicationContext ctx = new AnnotationConfigApplicationContext(DemoComponentScanConfiguration.class);         Dog dog = ctx.getBean(Dog.class);         System.out.println(dog);     } }

控制台打印结果如下

Dog{id=1, name='wangcai', age=3}

此时配置文件的属性已经注入成功

4.自动注入

在xml模式中有ref属性 可以将一个bean注入到另外一个bean中, 注解模式中也同样可以

@Autowired

给Dog的bean中注入 Person的Bean (即 给dog指定它的主人)

方法1 &rarr; 在属性上标注

@Component public class Dog {     // ......     @Autowired     private Person person; }

方法2 &rarr; 使用构造器注入方式

@Component public class Dog {     // ......     private Person person;      @Autowired     public Dog(Person person) {      this.person = person;     } }

方法3 &rarr; 使用setter方法注入

@Component public class Dog {     // ......     private Person person;          @Autowired     public void setPerson(Person person) {         this.person = person;     } }

jsR250规范下的@Resource

@Resource也是用来属性注入的注解

它与@Autowired的区别是:

  • @Autowired是按照类型注入

  • @Resource是按照属性名(也就是bean的名称)注入

@Resource 注解相当于标注 @Autowired @Qualifier

@Qualifier这里简要说明下,为指定bean的名称而存在,如果存在多个相同的bean,而bean的名称不同,我们可以使用@Autowired 配置  @Qualifier注解

如: 下面表示该Dog类注入的主人Bean是名称为 xiaowang的, 而当前容器内可能存在多个 主人bean对象 比如 xiaoli、xiaoming  ....

@Component public class Dog {     // ......     @Autowired     @Qualifier("xiaowang")     private Person person; }

下面如果使用@Resource 可以更方便些 代码如下

@Component public class Dog {     // ......     @Resource(name="xiaowang")     private Person person; }

JSR330规范下的@Inject

@Inject注解也是按照类型注入,与@Autowire的策略一样, 不过如要使用@Inject 需要额外的导入依赖

<!-- jsr330 --> <dependency>     <groupId>javax.inject</groupId>     <artifactId>javax.inject</artifactId>     <version>1</version> </dependency>

后面的使用方法就与SpringFramework 原生的 @Autowire + @Qualifier 相同了

@Component public class Dog {          @Inject // 等同于@Autowired     @Named("xiaowang") // 等同于@Qualifier     private Person person;

它与@Autowired的区别是:

  • @Autowired所在的包为 org.springframework.beans.factory.annotation.Autowired 即为  SpringFramework 提供的

  • @Inject所在的包为 javax.inject.Inject 属于JSR的规范  也就是说如果不使用SpringFramework时可以使用该注解

5. 复杂类型注入

Array注入

<property name="names">     <array>         <value>PoXing</value>         <value>LaoWang</value>     </array> </property>

List注入

<property name="tels">     <list>         <value>13000000000</value>         <value>13000000001</value>     </list> </property>

Set注入-

<!-- 已经提前声明好的Dog --> <bean id="wangcai" class="com.huodd.bean.ext.Dog"/> ---  <property name="dogs">     <set>         <bean class="com.huodd.bean.Dog"/>         <ref bean="wangcai"/>     </set> </property>

Map注入

<property name="homesMap">     <map>         <entry key="1" value="main">          <ref bean="myHome1" />         </entry>         <entry key="2" value="other">              <ref bean="myHome2" />         </entry>     </map> </property>

Properties注入

<property name="props">     <props>         <prop key="sex">男</prop>         <prop key="age">18</prop>     </props> </property>

面试题

1.@Autowired注入原理是什么?

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 先拿属性对应的类型,去IoC容器中找相应的Bean

  3. 如果没有找到 直接抛出NoUniqueBeanDefinitionException异常

  4. 如果找到一个 直接返回

  5. 如果找到多个相同类型的bean 再拿属性名去与这多个bean的id进行对比

  6. 如果有多个或者没有 则会抛出NoUniqueBeanDefinitionException异常

  7. 如果只有一个 直接返回

2.依赖注入的方式有哪些,都有什么区别

如何理解IoC的依赖注入

3.自动注入的注解对比

如何理解IoC的依赖注入

@Qualifier :如果被标注的成员/方法在根据类型注入时发现有多个相同类型的 Bean ,则会根据该注解声明的 name 寻找特定的  bean

@Primary :如果有多个相同类型的 Bean 同时注册到 IOC 容器中,使用 “根据类型注入” 的注解时会注入标注 @Primary 注解的  bean 即默认策略

4.使用依赖注入有什么优缺点

依赖注入作为 IOC 的实现方式之一,目的就是解耦,我们不需要直接去 new 那些依赖的类对象就可以直接从容器中去取来使用,  如果组件存在多级依赖,依赖注入可以将这些依赖的关系简化。

依赖对象的可配置:通过 xml 或者注解声明,可以指定和调整组件注入的对象,借助 Java  的多态特性,可以不需要大批量的修改就完成依赖注入的对象替换

感谢各位的阅读,以上就是“如何理解IoC的依赖注入”的内容了,经过本文的学习后,相信大家对如何理解IoC的依赖注入这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 如何理解IoC的依赖注入

本文链接: https://www.lsjlt.com/news/83975.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何理解IoC的依赖注入
    这篇文章主要讲解了“如何理解IoC的依赖注入”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解IoC的依赖注入”吧! 一、注解驱动IoCxml...
    99+
    2022-10-19
  • Laravel核心原理学习:依赖注入、IOC容器
    欢迎指正内容不严谨或有误的地方! 使用Laravel的过程中经常会遇到一些名词(服务提供者、依赖注入、IOC容器之类的概念),每次都是匆匆扫俩眼手册,没有机会深究。今天就花些时间学习,若有不足,后...
    99+
    2023-09-05
    laravel 学习 php
  • 如何理解SpringFramework与IOC依赖查找
    这篇文章主要介绍“如何理解SpringFramework与IOC依赖查找”,在日常操作中,相信很多人在如何理解SpringFramework与IOC依赖查找问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理...
    99+
    2023-06-15
  • 如何简单的理解依赖注入详解
    依赖注入(Dependency Injection,简称DI)是一种设计模式,用于解耦代码中的依赖关系。简单来说,依赖注入就是将一个...
    99+
    2023-08-14
    依赖注入
  • 使用Spring自定义实现IOC和依赖注入(注解方式)
    目录大致思路:注解实现方式:xml实现方式:1. 引入相关jar2. 定义注解类ExtService是注解类的, ExtResource是注解属性的3.定义一个借口4. 接口和使用注...
    99+
    2022-11-12
  • 理解ASP.NET Core 依赖注入(Dependency Injection)
    目录依赖注入什么是依赖注入依赖注入有什么好处ASP.NET Core内置的依赖注入服务生存周期服务释放TryAdd{Lifetime}扩展方法解析同一服务的多个不同实现Replac&...
    99+
    2022-11-12
  • .net程序开发IOC控制反转和DI依赖注入详解
    目录IOC控制反转DI依赖注入服务生命周期其它IOC控制反转 大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果类 ...
    99+
    2022-11-13
    .net 控制反转依赖注入 .net IOC DI
  • Spring的DI依赖注入详解
    目录1、什么是DI依赖注入?2、利用 set 方法给属性赋值3、利用 构造函数 给属性赋值总结:1、什么是DI依赖注入? spring动态的向某个对象提供它所需要的其他对象。这一点是...
    99+
    2022-11-13
  • AndroidHilt依赖注入的使用讲解
    目录什么是依赖注入使用依赖注入的好处Hilt中常用的预定义限定符@HiltAndroidApp@AndroidEntryPoint@Module@InstallIn@Provides...
    99+
    2023-01-16
    Android Hilt依赖注入 Android Hilt Android依赖注入
  • 如何理解Angular中的组件通讯和依赖注入
    这篇文章给大家介绍如何理解Angular中的组件通讯和依赖注入,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 Angular组件间怎么进行通讯?依赖注入是什...
    99+
    2022-10-19
  • AngularJS如何实现依赖注入
    小编给大家分享一下AngularJS如何实现依赖注入,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!简介:首先我们需要理解什么是依...
    99+
    2022-10-19
  • 理解Spring中的依赖注入和控制反转
    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框...
    99+
    2023-05-30
    spring 依赖注入 控制反转
  • laravel依赖注入的原理是什么
    Laravel的依赖注入原理是基于反射的。依赖注入是一种设计模式,它的目的是通过将依赖对象的实例传递给需要它们的对象,来解耦和提高代...
    99+
    2023-10-22
    laravel
  • spring依赖注入的原理是什么
    Spring依赖注入的原理是通过IOC(Inversion of Control)容器来实现的。IOC容器是Spring框架的核心,...
    99+
    2023-09-29
    spring
  • php依赖注入的原理是什么
    PHP依赖注入的原理是通过将一个对象的依赖关系通过构造函数、方法参数或者setter方法的方式进行传递。依赖注入的目的是解耦,使得代...
    99+
    2023-09-21
    php
  • angular依赖注入的原理是什么
    Angular的依赖注入(Dependency Injection)是一种设计模式,用于管理组件之间的依赖关系。它的原理是通过将组件...
    99+
    2023-09-21
    angular
  • Angular中的依赖注入如何使用
    这篇文章主要介绍了Angular中的依赖注入如何使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Angular中的依赖注入如何使用文章都会有所收获,下面我们一起来看看吧。译者添加:维基百科中指出 -- 在软件...
    99+
    2023-07-04
  • 如何用Java注解和反射实现依赖注入
    目录概述定义注解为被注入的方法添加注解通过反射处理注解概述 在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇...
    99+
    2022-11-12
  • Angular中如何使用依赖注入
    这篇文章主要介绍了Angular中如何使用依赖注入,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。useFactory、useClass、us...
    99+
    2022-10-19
  • ASP.NET MVC如何实现依赖注入
    这篇文章主要介绍了ASP.NET MVC如何实现依赖注入,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言在java的spring中有自动注入功能,使得代码变得更加简洁灵活,...
    99+
    2023-06-28
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作