1.概述

Spring中IOC可以通过注解方式实现,只要在spring的配置文件applicationContext.xml中配置开启了包扫描Spring会自动扫描指定包及其子孙包。

<!-- 开启包扫描 -->
<context:component-scan base-package="cn.tedu.beans"/>

在类上添加注解@Component则实现了通过注解注册bean,此时这个类就被spring管理了。具体过程可以描述为:

当Spring容器解析到@Component注解时,创建当前类的bean在spring容器中进行管理,在创建bean的过程中发现了@Autowired注解,会根据当前bean类型,寻找在spring中是否存在该类型的bean,找到直接注入,如果找不到还会检查是否有子孙类、实现类存在,如果存在唯一的则自动注入,如果还是没有找到或找到多个无法注入,则还会按照属性名对应id去查找对应的bean,如果存在则注入,如果还是没有找到则抛出异常。也可以额外配置@Qualifier(value="dog1")注解强制要求按照id寻找bean,则此时会直接使用给定的id寻找bean,而不会进行基于类型的匹配。

@Autowired:

  • 在bean中的属性上通过@Autowired实现自定义bean类型的属性注入
  • 使用是对应的bean必须被spring管理,即手动配置了bean或者在类上添加了@Component注解

DI:就是注入功能,通俗的说就是给IOC创建出来的对象属性赋值

2.只有@Autowired,没有@Qualifier情况

先按照类型匹配,即按照当前bean类型寻找是否存在指定类型的bean
如果找到唯一的bean直接注入
如果找不到或找到多个则开始按照id注入(默认取当前属性名)
找到唯一的则注入,找不到则抛出异常,不可能找到多个。

具体的通过如下代码描述:

如下有一个英雄类hero他有一个属性,可以带一只狗,提供了狗类Dog,提供了狗类的子类金毛狗JMDog,哈士奇狗HSQDog

类结构如下:

情况一:在英雄类中只添加了@Autowired注解,且只将Dog类交给Spring容器管理,那么按照顺序应该是先按照类型匹配,当前给出的是Dog类

经过测试@Autowired注解按照类型就找到了唯一的bean--Dog类于是注入该类

情况二:将Dog的子类JMDog,HSQDog 也加入spring容器管理,此时按照类型去找就会找到多个,因为JMDog,HSQDog都是Dog类,此时按照id去找

id为dog所以找到的就是Dog类,然后注入

 如果将对象名改为hsqdog,此时会抛出异常,原因是因为注解的推断规则

(推断规则请查阅文章:https://blog.csdn.net/qq_32224047/article/details/107005905

根据推断规则,如果要找哈士奇类,给的id名应该是HSQDog,验证成功,完全符合注解的推断规则

 如果一定要用hsqdog那么只需要在HSQDog类上指定id就行

测试根据hsqdog 这个id能找到 HSQDog类

情况三,如果根据类型和id 都找不到就会抛出异常,如给一个不存在的京巴狗,JBDog,那么就不会找到,抛出异常

 

3.@Autowired和@Qualifier一起使用

  •  此注解可以配合@Autowired使用
  •  一旦同时配置@Autowired和@Qualifier,则不再按照类型去匹配,直接按照id匹配
  • 如果按照id能找到就注入,找不到就抛出异常
  • 此注解可以指定要使用的id,如果不指定默认是空串,会抛出异常

情况一:在@Qualifier上指定id,那么找到的就是该id的bean,找不到抛出异常,如下指定id为JMDog,找到的就是JMDog

情况二:当不指定id时,默认会给一个空串,所以空串是不会找到的,使用@Qualifier必须指定一个id

查看注解源码,默认给的就是空串

因为是空串,找不到就抛出异常 

 

在软件分层时,一般都会定义一个接口就对应的实现类,然后将实现类交给Spring容器管理,当在其他层需要使用时通过@Autowired注入

代码如下:

在service层定义了接口及实现类,并将实现类交给spring容器管理(采用@Service--具体将类注册为bean需要如何使用正确的注解,可以查阅文章:https://blog.csdn.net/qq_32224047/article/details/107010098

 当控制层调用Service层时,等号左边为接口对象等号左边赋值为null,让spring容器自动注入(这种写法降低了耦合),当@Autowired扫描到时根据自动推断规则,就找到了实现类UserServiceImpl,并注入该实现类的对象,因为这个实现类交给了spring容器管理,因为UserService是接口,接口不会创建对象所以即使将接口交给spring容器管理,找到的还是他对应的实现类。

3.执行流程图

 

4.@Autowired(required=false)

4.1描述:

在使用spring开发过程中,我们基本上都是使用@Autowired这个注解,用来注入已有的bean。但是有些时候,会注入失败。当我们加上参数(required=false)就能解决

4.2required属性:

  • @Autowired(required=true):当使用@Autowired注解的时候,其实默认就是@Autowired(required=true),表示注入的时候,该bean必须存在,否则就会注入失败。
  • @Autowired(required=false):表示忽略当前要注入的bean,如果有直接注入,没有跳过,不会报错。

 4.3使用场景

我们的正常使用会在Controller层注入service,在service中注入mapper。

但是如果有一个公用方法,需要注入某个元素,并且这个方法在公用模块里。当该模块被引入其他项目中,该项目中并需要注入所需的bean时,就出现错误。那么问题来了,我们项目中并不需要该要注入的类,使得整个项目报错

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐