Spring IoC DI 之 属性注入

news/2024/9/25 21:16:56/

 一、DI (依赖注入)

依赖注入(DI)是一种实现控制反转(IoC)的技术,可以在运行时动态地向应用程序提供其所需的依赖。在 Spring 框架中,DI 是一种常用的实践,有助于提高代码的模块化和灵活性。下面是依赖注入的一些关键点和优势:

依赖注入的工作原理
  1. 容器管理

    • 在 Spring 中,容器负责创建和管理对象(即 Beans)。开发者只需要通过配置(可以是 XML 文件、注解或 Java 配置类)指定依赖关系。
  2. 注入方式

    • 构造器注入:通过构造函数传递依赖。
    • 设置器注入:通过 JavaBean 属性的 setter 方法传递依赖。
    • 字段注入:直接在字段上注入依赖,通常使用 @Autowired 注解。
  3. 运行时绑定

    • 依赖注入是在运行时处理的,这意味着应用程序的组件可以在不修改代码的情况下,通过更改配置来使用不同的依赖实现。

二、使用 字段注入自动注入 Bean

在 Spring 的组件(如由 @Component, @Service, @Controller 等注解标记的类)中,你可以使用 @Autowired 注解自动注入 Bean。这是推荐的方法,因为它减少了对 Spring API 的直接依赖,并且使得代码更加简洁。

java">@Component
public class UserService {@Autowiredprivate User user;public void displayUser() {System.out.println("User Name: " + user.getName());}
}

Spring 应用中使用 @Autowired 注解自动注入 Bean 且存在多个相同类型的 Bean 时,会出现冲突,因为 Spring 不知道应该注入哪一个。为了解决这个问题,Spring 提供了几种方法来指定要注入的具体 Bean,确保准确性和灵活性。

1)指定Bean 注入
a) 使用 @Qualifier 注解

@Qualifier 注解用来进一步细化 @Autowired 的注入选择。通过为每个 Bean 定义一个名称,然后在注入时指定这个名称,可以控制哪一个 Bean 被注入。

java">@Component
public class VehicleService {@Autowired@Qualifier("car")private Vehicle vehicle;public void service() {vehicle.performService();}
}@Component("car")
public class Car implements Vehicle {@Overridepublic void performService() {System.out.println("Servicing a car");}
}@Component("bike")
public class Bike implements Vehicle {@Overridepublic void performService() {System.out.println("Servicing a bike");}
}

在这个例子中,我们有两个 Vehicle 类型的 Bean,分别是 CarBike。使用 @Qualifier("car") 告诉 Spring 在注入 Vehicle 类型的依赖时使用名为 "car" 的 Bean 

b)  使用 @Primary 注解

当你想要在多个相同类型的 Bean 中指定一个“默认”Bean 时,可以使用 @Primary 注解。当存在多个 Bean 且其中一个被标记为 @Primary,Spring 会优先注入这个 Bean。

java">@Component
@Primary
public class Car implements Vehicle {@Overridepublic void performService() {System.out.println("Servicing a car");}
}@Component
public class Bike implements Vehicle {@Overridepublic void performService() {System.out.println("Servicing a bike");}
}@Component
public class VehicleService {@Autowiredprivate Vehicle vehicle;  // 默认注入 @Primary 标记的 Beanpublic void service() {vehicle.performService();}
}

在这个例子中,Car 类被标记为 @Primary,因此它会被默认注入到 VehicleService 中,除非使用 @Qualifier 明确指定其他 Bean。

c)  使用特定方法命名或 @Bean 注解中的名称

在 Java 配置类中,你可以通过方法名称或在 @Bean 注解中指定名称来控制 Bean 的标识符。然后,可以结合使用 @Autowired@Qualifier

java">@Configuration
public class AppConfig {@Bean(name = "car")public Vehicle car() {return new Car();}@Bean(name = "bike")public Vehicle bike() {return new Bike();}
}

然后,使用 @Qualifier 来指定注入哪一个。

通过这些方法,你可以在 Spring 中精确控制哪个 Bean 被注入到有多个相同类型的 Bean 的情况下,从而保证应用的正确性和灵活性。

2)使用 @Resource 或 @Inject 注解

@Resource@Inject 是 JSR-250 和 JSR-330 的标准 Java 注解,分别来自 Java EE 和依赖注入规范。它们与 @Autowired 类似,但略有不同的注入语义和配置方式。

示例代码(使用 @Resource):

java">@Component
public class UserService {@Resource(name="user")private User user;public void displayUser() {System.out.println("User Name: " + user.getName());}
}

三、  构造方法注入

这种方式是最推荐的,因为它确保了所有的依赖在对象被创建之前就已经准备好了。

java">@Component
public class UserService {private final UserRepository userRepository;@Autowiredpublic UserService(UserRepository userRepository) {this.userRepository = userRepository;}public void performAction() {System.out.println("Action performed with user repository.");}
}

四、Setter 方法注入

这种方法适用于可选依赖,或者在对象创建之后还可以更改依赖的情况

java">@Component
public class NotificationService {private EmailService emailService;@Autowiredpublic void setEmailService(EmailService emailService) {this.emailService = emailService;}public void sendNotification(String message, String recipient) {emailService.sendEmail(message, recipient);}
}@Component
public class EmailService {public void sendEmail(String message, String recipient) {System.out.println("Email sent to " + recipient + " with message: " + message);}
}


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

相关文章

MySQL内存(Buffer Pool)

Buffer Pool MySQL 的数据存在磁盘,但是不能每次读取数据都从磁盘里去,这样磁盘IO太频繁,存在性能问题。 InnoDB设计了一个缓存池(Buffer Pool),缓冲池在内存中。 默认配置Buffer Pool大小为128MB&#xf…

【Rust练习】16.模式

文章题目来自:https://practice-zh.course.rs/pattern-match/patterns.html 1 🌟🌟 使用 | 可以匹配多个值, 而使用 … 可以匹配一个闭区间的数值序列 fn main() {} fn match_number(n: i32) {match n {// 匹配一个单独的值1 > println!(…

关于有源蜂鸣器及无源蜂鸣器的区别及驱动各类单片机案例

关于有源蜂鸣器及无源蜂鸣器的区别及驱动各类单片机案例 有源蜂鸣器与无源蜂鸣器区别有源蜂鸣器无源蜂鸣器模块化有源蜂鸣器及无源蜂鸣器驱动方式的说明 有源、无源蜂鸣器代码驱动总结 有源蜂鸣器与无源蜂鸣器区别 有源蜂鸣器与无源蜂鸣器区别在于是否有振荡源。 有源蜂鸣器即…

sqoop的安装与简单使用

文章目录 一、安装1、上传,解压,重命名2、修改环境变量3、修改配置文件4、上传驱动包5、拷贝jar包 二、import命令1、将mysql的数据导入到hdfs上2、将mysql的数据导入到hive上3、增量导入数据 三、export命令1、从hdfs导出到mysql中2、从hive导出到mysql…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-24

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-24 1. Enriching Datasets with Demographics through Large Language Models: What’s in a Name? K AlNuaimi, G Marti, M Ravaut, A AlKetbi, A Henschel… - arXiv preprint arXiv …, 2024 通过大型语言…

【Linux基础IO】深入解析Linux基础IO缓冲区机制:提升文件操作效率的关键

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:Linux “ 登神长阶 ” 🤡往期回顾🤡:暂无 🌹🌹期待您的关注 🌹🌹 ❀Linux基础IO 📒1. 什么是缓…

k8s中,服务的自动注册、自动感知、负载均衡,三个功能的含义及测试验证

自动感知,指的是客户端只用访问服务的ip,而不用关心pod在哪个节点,以及pod的ip是多少。 服务可以自动感知pod的位置及ip,核心是通过selector标签选择器找到pod 自动注册,指的是服务创建之后,会自动在k8s的…

高效音频格式转换实战:使用Python和FFmpeg处理MP3到WAV的转换20240918

高效音频格式转换实战:使用Python和FFmpeg处理MP3到WAV的转换 引言 在现代音频处理工作中,音频文件格式的转换已成为日常操作之一。无论是为了兼容不同设备,还是进行更高质量的音频编辑,掌握如何快速、准确地转换音频格式是必不…