六、深入了解DI

news/2025/1/31 14:34:57/

依赖注入是⼀个过程,是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源,⽽资源指的就是对象. 在上⾯程序案例中,我们使⽤了 @Autowired 这个注解,完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中。

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

1. 属性注入(FieldInjection)

2. 构造⽅法注入(ConstructorInjection)

3. Setter 注入(SetterInjection)

4.1 属性注入

属性注⼊是使⽤ @Autowired 实现的,将Service类注⼊到Controller类中.

Service 类的实现代码如下:

java">@Service
public class UserService {public void sayHi() {System.out.println("Hi,UserService");}
}

Controller 类的实现代码如下:

java">@Controller
public class UserController {@Autowiredprivate UserService userService;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();}
}

获取Controller中的sayHi方法:

java">public class DemoApplication {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(DemoApplication.class, args);//从Spring上下文中获取对象UserController userController = (UserController) context.getBean("userController");//使用对象userController.sayHi();}
}

运行结果: 

去掉@Autowired,再运行⼀下程序看看结果:

4.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,如下代码所示:

java">
@Controller
public class UserController {private UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}public void sayHi() {System.out.println("hi,UserController...");userService.sayHi();}
}

注意事项:如果类只有⼀个构造方法,那么@Autowired 注解可以省略;如果类中有多个构造方法, 那么需要添加上@Autowired 来明确指定到底使用哪个构造方法。

4.3 Setter 注入

Setter 注入和属性的Setter方法实现类似,只不过在设置set方法的时候需要加上@Autowired 注 解,如下代码所示例:

java">@Controller
public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService service) {this.userService = service;}public void sayHi() {System.out.println("hi,UserController...");userService.sayHi();}
}

4.4 三种注入优缺点分析

优点缺点
属性注入简洁,使用方便

1、只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指 针异常)

2、不能注⼊⼀个Final修饰的属性

构造函数注入(Spring4.X推荐)

1、可以注⼊final修饰的属性

2、注⼊的对象不会被修改

3、 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法.

4、 通⽤性好,构造⽅法是JDK⽀持的,所以更换任何框架,他都是适⽤的

注⼊多个对象时,代码会⽐较繁琐
Setter注入(Spring3.X推荐)方便在类实例之后,重新对该对象进⾏配置或者注⼊

1、不能注⼊⼀个Final修饰的属性

2、注⼊对象可能会被改变,因为setter⽅法可能会被多次调⽤,就有被修改的⻛险

4.5 @Autowired存在问题

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

java">@Component
public class BeanConfig {@Bean("u1")public UserInfo user1() {UserInfo userInfo = new UserInfo();userInfo.setName("张三");userInfo.setAge(18);return userInfo;}@Beanpublic UserInfo user2() {UserInfo userInfo = new UserInfo();userInfo.setName("李四");userInfo.setAge(20);return userInfo;}}
java">@Controller
public class UserController {@AutowiredUserService userService;@AutowiredUserInfo userInfo;public void sayHi() {System.out.println("hi,UserController...");userService.sayHi();}
}

编译时出现报错

 报错的原因是,非唯一的Bean对象。

Spring提供了以下几种注解的解决方案:

• @Primary

• @Qualifier

• @Resource

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

java">@Component
public class BeanConfig {@Primary //指定该bean为默认的bean的实现@Bean("u1")public UserInfo user1() {UserInfo userInfo = new UserInfo();userInfo.setName("张三");userInfo.setAge(18);return userInfo;}@Bean("u2")public UserInfo user2() {UserInfo userInfo = new UserInfo();userInfo.setName("李四");userInfo.setAge(20);return userInfo;}}

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

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

java">@Controller
public class UserController {@Qualifier("u2")@Autowiredprivate UserInfo userInfo;public void sayHi() {System.out.println("hi,UserController...");System.out.println(userInfo);}
}

运行结果:

 使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注⼊的bean的名称。

java">@Controller
public class UserController {@Resource(name="u2")private UserInfo userInfo;public void sayHi() {System.out.println("hi,UserController...");System.out.println(userInfo);}
}

运行结果:

@Autowird与@Resource的区别
1、@Autowired是spring框架提供的注解,而@Resource是JDK提供的注解
2、@Autowired默认是按照类型注入,而@Resource是按照名称注入.相比于@Autowired来说         @Resource支持更多的参数设置,例如name设置,根据名称获取Bean.

Autowired装配顺序


http://www.ppmy.cn/news/1568171.html

相关文章

第 10 课 Python 内置函数 (增补)

1.enumerate enumerate() 接受一个可迭代对象作为输入,并返回一个枚举对象这个枚举对象包含了原始可迭代对象中的每个元素以及对应的索引它允许在循环中同时获取索引和值,这对于需要索引的情况非常方便 作用:在循环中需要同时访问索引和值时非…

C语言连接Mysql

目录 C语言连接Mysql下载 mysql 开发库 方法介绍mysql_init()mysql_real_connect()mysql_query()mysql_store_result()mysql_num_fields()mysql_fetch_fields()mysql_fetch_row()mysql_free_result()mysql_close() 完整代码 C语言连接Mysql 下载 mysql 开发库 方法一&#xf…

【Elasticsearch】doc_values 可以用于查询操作

确实,doc values 可以用于查询操作,尽管它们的主要用途是支持排序、聚合和脚本中的字段访问。在某些情况下,Elasticsearch 也会利用 doc values 来执行特定类型的查询。以下是关于 doc values 在查询操作中的使用及其影响的详细解释&#xff…

深度学习笔记——正则化

大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本笔记介绍深度学习中常见的正则化。 文章目录 正则化L1 正则化(Lasso)原理使用场景优缺点 L2 正则化(Ridge)原理使用…

【论文推荐|深度学习,滑坡检测,多光谱影像,自然灾害,遥感】2022年Landslide4Sense竞赛成果:基于多源卫星影像的先进滑坡检测算法研究(五)

【论文推荐|深度学习,滑坡检测,多光谱影像,自然灾害,遥感】2022年Landslide4Sense竞赛成果:基于多源卫星影像的先进滑坡检测算法研究(五) 【论文推荐|深度学习,滑坡检测&#xff0c…

python3+TensorFlow 2.x(四)反向传播

目录 反向传播算法 反向传播算法基本步骤: 反向中的参数变化 总结 反向传播算法 反向传播算法(Backpropagation)是训练人工神经网络时使用的一个重要算法,它是通过计算梯度并优化神经网络的权重来最小化误差。反向传播算法的核…

kaggle视频追踪NFL Health Safety - Helmet Assignment

3年前的比赛了,检测视频中的头盔,通过对比赛录像的分析,正确指派球员。每个进攻都有两个相关的视频,一个是边线视角,另一个是端区视角,而且这两个视频是同步的,即视频中的每一帧都是对应的。我用…

DiffuEraser: 一种基于扩散模型的视频修复技术

视频修复算法结合了基于流的像素传播与基于Transformer的生成方法,利用光流信息和相邻帧的信息来恢复纹理和对象,同时通过视觉Transformer完成被遮挡区域的修复。然而,这些方法在处理大范围遮挡时常常会遇到模糊和时序不一致的问题&#xff0…