Java Spring框架 III 之 Spring框架扩展

本文深入探讨了Spring框架的核心概念IoC与DI,解析了@Qualifier、@Resource及@Autowired注解的应用场景与区别,同时提供了关于构造方法使用的指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java Spring框架 III 之 Spring框架扩展

Spring框架扩展

1.IoC与DI

● IoC(Inversion of Control:控制反转)是Spring框架的核心,在传统
的开发模式下,是由开发者创建对象、为对象的属性赋值、管理对象的作
用域和生命周期等,所以,是开发者拥有“控制权”
,当使用了Spring之
后,这些都交给Spring框架去完成了,开发者不必关心这些操作的具体实
现,所以,称之为“控制反转”
● 无论是创建对象,还是自动装配等等,只要是Spring创建并管理对象的操
作,都可以称之为Spring IoC的过

DI(Dependency Injection:依赖注入)是Spring框架实现IoC的核心实
现,当某个类中声明了另一个类的属性(例如在UserController类中声明
了UserMapper类型的属性),则称之为依赖(即UserController依赖了
UserMapper),Spring框架会帮你完成依赖项的赋值,只是你在你的代
码中看不到赋值过程或赋值符号,所以称之为注入

关于IoC与DI的关系,可以描述为:Spring通过DI实现了IoC,所以,IoC
是一种目标,而DI是实现此目标的重要手段

2.@Qualifier

@Qualifier注解是在自动装配机制中,用于指定beanName的注解
● 通常是因为存在多个类型匹配的Bean,但是所有Bean的beanName与被
装配的属性名称/参数名称都不匹配,且不想修改beanName也不想修改
属性名称/参数名称,则可以通过@Qualifier指定beanName – 这种现象在开发实践中并不多

● 在自动装配属性时指定beanName
在这里插入图片描述
● 在自动装配方法参数时指定beanName
在这里插入图片描述

3.关于构造方法

● 当通过组件扫描创建对象时,Spring会自动调用组件类的构造方法,此过
程中会使用到反射,所以可以无视构造方法的访问权限
● 如果类中仅有1个构造方法,Spring会自动调用这个构造方法
● 如果类中没有显式的添加构造方法,根据Java的机制,会由编译器添加默
认构造方法,相当于有1个构造方法
● 如果类中有多个构造方法,默认情况下,Spring会自动调用无参数构造方
法(如果存在的话),如果某个构造方法添加了@Autowired,则Spring
会自动调用添加了此注解的构造方法

● 被Spring调用的构造方法是允许有参数的,作为开发者,你需要保证
Spring可以利用自动装配机制为参数注入值(你需要保证Spring容器中
存在匹配的值),否则会导致NoSuchBeanDefinitionException

4.@Resource注解

● @Resource注解是javax.annotation包中的
● 如果某属性添加了@Resource注解,Spring也可以实现自动装配
在这里插入图片描述
● @Resource注解的装配机制是:先尝试根据名称进行装配(即:要求属
性名称与beanName相同),如果失败,则尝试根据类型装配,如果不存
在类型的Bean,则抛出NoSuchBeanDefinitionException,如果只有1
个匹配类型的Bean,则装配成功,如果匹配类型的Bean超过1个,则抛
出NoUniqueBeanDefinitionException

● 在开发实践中,绝大部分类型的Bean都只有1个,无论是@Autowired还
是@Resource,当匹配类型的Bean有且仅有1个时,都可以成功装配,
所以,在绝大部分情况下,这2个注解的装配机制的差异对于开发人员来
说是无感的

● 当需要讨论@Autowired与@Resource的区别时,除了这2个注解所在的
包不同、装配机制不同以外,还存在以下区别:
– @Autowired可以添加在构造方法的声明之前,@Resource不可以
– @Resource可以添加在类的声明之前(但不会装配属性的值),@Autowired不可

– 当存在多个同类型的Bean时
– 当装配属性时,@Autowired需要通过@Qualifier指定beanName,而@Resource可以
直接配置name属性以指定beanName – 当装配方法的参数时(例如添加了@Autowired的构造方法的参数),@Autowired仍可
以使用@Qualifier指定beanName,而@Resource无法解决此问题

● 综合来看,由于@Autowired是Spring框架专门定制的注解,且
@Autowired可以添加在构造方法上,相比@Resource有更多的应用场景
(虽然不一定真的需要这样用),所以,在开发实践中,当需要使用注解
显式的表示自动装配时,推荐优先使用@Autowired

5.@Autowired的警告

● 当你在属性上添加@Autowired时,在IntelliJ IDEA中会有浅灰色的下划
线提示警告,例如:
在这里插入图片描述
● 此警告内容为:Field Injection is not recommended,可译为:字段
(类的属性)注入是不推荐的
● 假设某开发人员不是通过Spring容器获取UserController的对象,而是通
过传统方式,使用new关键字自行创建对象,且忽略了为userMapper属
性赋值(此属性是private的,对外不可见,忽略了很常见),则会导致
userMapper一直是默认的null值,后续调用userMapper的方法时就会出
现NPE,这被视为字段注入的不足之处
– 暂不关心为什么不通过Spring容器获取对象

● 建议的解决方案是这样的:

@Controller
public class UserController {
private UserMapper userMapper;
public UserController(UserMapper userMapper) {
this.userMapper = userMapper;
}
public void reg() {
System.out.println("UserController.reg() >> 控制器即将执行用户注册……");
System.out.println(userMapper.getClass().getName());
userMapper.insert();
}
}

● Spring有非常完善的调用构造方法的机制,并且也可以对构造方法中的参
数注入值,甚至存在多个匹配类型对象时还可以使用@Qualifier指定
beanName,所以,只要构造方法中的代码能够对属性赋值,就可以实现
和属性上自动装配完全相同的效果
● 只要将必要的值声明为构造方法的参数,无论是Spring创建对象,还是人
为创建对象,都需要提供此参数值,除非恶意的传入null值,否则,不会
出现NPE问题,所以,此做法是被推荐的

● 使用构造方法虽然安全,不会出现NPE,但是,当需要被赋值的属性的数
量出现增或减时,都需要调整构造方法,当属性数量较多时,构造方法的
参数也会变多,这些都是在开发实践中非常现实的问题
● 由于字段注入的NPE问题只是开发阶段人为错误使用导致的,出现概率非
常低、可控、容易解决,且字段注入的语法简洁、直观,所以,在开发实
践中,字段注入仍是最常见的用法

我是将军;我一直都在,。!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值