当前位置: 首页 > news >正文

控制反转(IoC)和依赖注入(DI)实现及常用注解

在Spring框架里,控制反转(IoC)和依赖注入(DI)是核心特性,以下将介绍实现它们的各种方式以及常用注解。

配置文件方式

详细版:

Spring IoC与DI详解:从Bean概念到手写实现

XML 配置

XML 配置是 Spring 早期实现 IoC 和 DI 的主要方式,通过 <bean> 标签定义 Bean,使用不同的属性和子标签来完成依赖注入。

1. Bean 定义与基本属性
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义一个 Bean,id 是唯一标识,class 是该 Bean 对应的类 --><bean id="userService" class="com.example.service.UserService"><!-- 可以通过 init-method 和 destroy-method 指定 Bean 的初始化和销毁方法 --><property name="initMethod" value="init"/><property name="destroyMethod" value="destroy"/></bean>
</beans>

在上述示例中,id 是 Bean 在 Spring 容器中的唯一标识,class 指定了该 Bean 对应的 Java 类。init-method 和 destroy-method 可以让开发者在 Bean 初始化和销毁时执行特定的方法。

2. 构造函数注入
<bean id="userService" class="com.example.service.UserService"><!-- 通过 constructor-arg 标签进行构造函数注入 --><constructor-arg ref="userDao"/>
</bean>
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>

constructor-arg 标签用于向构造函数传递参数,ref 属性表示引用另一个 Bean。这里 UserService 的构造函数接收一个 UserDao 类型的参数,通过 ref 引用了 userDao 这个 Bean。

3. Setter 方法注入
<bean id="userService" class="com.example.service.UserService"><!-- 通过 property 标签进行 Setter 方法注入 --><property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>

property 标签用于调用 Setter 方法注入依赖,name 属性指定要注入的属性名,ref 引用另一个 Bean。

4. 自动装配
<bean id="userService" class="com.example.service.UserService" autowire="byType"/>
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>

autowire 属性可以指定自动装配模式,常见的有 byName(按属性名匹配)、byType(按类型匹配)等。上述示例中,userService 会根据 byType 模式自动注入 UserDao 类型的 Bean。

注解方式

先列出表格:

类别注解作用使用示例注意事项
组件定义注解@Component通用注解,将类标记为Spring组件,Spring自动扫描并纳入容器管理java<br>@Component<br>public class GeneralComponent {<br> // 类的具体实现<br>}<br>
@Service@Component的特化注解,标记业务逻辑层类java<br>@Service<br>public class UserService {<br> public void handleBusiness() {<br> // 业务逻辑处理<br> }<br>}<br>
@Repository@Component的特化注解,标记数据访问层类,还可进行数据访问异常转换java<br>@Repository<br>public class UserDaoImpl implements UserDao {<br> public User findById(Long id) {<br> // 根据ID查找用户的逻辑<br> return null;<br> }<br>}<br>
@Controller@Component的特化注解,标记Spring MVC控制器类,处理HTTP请求java<br>@Controller<br>@RequestMapping("/user")<br>public class UserController {<br> @GetMapping("/info")<br> @ResponseBody<br> public String getUserInfo() {<br> return "User Info";<br> }<br>}<br>需结合Spring MVC相关注解使用
依赖注入注解@AutowiredSpring提供的自动装配注解,默认按类型装配,可用于字段、构造函数、Setter方法java<br>@Component<br>public class UserController {<br> @Autowired<br> private UserService userService;<br>}<br>存在多个相同类型Bean时会有歧义,需结合@Qualifier使用
@Qualifier@Autowired配合,当存在多个相同类型Bean时,指定要注入的Bean名称java<br>@Component<br>public class UserController {<br> @Autowired<br> @Qualifier("specificUserService")<br> private UserService userService;<br>}<br>@Qualifier中的名称要与目标Bean的名称一致
@ResourceJSR - 250规范注解,默认按名称注入,未指定名称则按类型注入java<br>@Component<br>public class UserController {<br> @Resource(name = "userService")<br> private UserService userService;<br>}<br>
@InjectJSR - 330规范注解,功能类似@Autowiredjava<br>import javax.inject.Inject;<br>@Component<br>public class UserController {<br> @Inject<br> private UserService userService;<br>}<br>需要引入JSR - 330相关依赖
配置类注解@Configuration标记Java配置类,类中可用@Bean定义Beanjava<br>@Configuration<br>public class AppConfig {<br> @Bean<br> public UserService userService() {<br> return new UserService();<br> }<br>}<br>
@Bean@Configuration类的方法上使用,方法返回值作为Bean注册到容器java<br>@Configuration<br>public class AppConfig {<br> @Bean<br> public UserDao userDao() {<br> return new UserDaoImpl();<br> }<br>}<br>方法名可作为Bean的默认名称,可在方法中进行复杂初始化操作
组件定义注解

这些注解用于将类标记为 Spring 组件,让 Spring 容器自动扫描并管理这些类。

1. @Component
import org.springframework.stereotype.Component;@Component
public class UserService {// 类的具体实现public void doSomething() {System.out.println("UserService is doing something.");}
}

@Component 是一个通用的组件注解,被标记的类会被 Spring 容器识别并创建为 Bean。

2. @Service
import org.springframework.stereotype.Service;@Service
public class UserService {// 业务逻辑实现public void saveUser() {// 保存用户的业务逻辑}
}

@Service 是 @Component 的特化注解,通常用于标记业务逻辑层的类,语义更加明确,方便代码的阅读和维护。

3. @Repository
import org.springframework.stereotype.Repository;@Repository
public class UserDaoImpl implements UserDao {// 数据访问实现public User findUserById(Long id) {// 根据 ID 查询用户的逻辑return null;}
}

@Repository 同样是 @Component 的特化注解,主要用于标注数据访问层的类。Spring 还会对标注了 @Repository 的类进行数据访问异常的转换,方便统一处理异常。

4. @Controller
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
@RequestMapping("/user")
public class UserController {// 处理请求的方法@GetMapping("/hello")@ResponseBodypublic String sayHello() {return "Hello, User!";}
}

@Controller 是 @Component 的特化注解,用于标记 Spring MVC 的控制器类,负责处理 HTTP 请求。

依赖注入注解

这些注解用于实现依赖的自动注入,减少手动配置的工作量。

1. @Autowired
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class UserController {// 字段注入@Autowiredprivate UserService userService;// 构造函数注入private UserDao userDao;@Autowiredpublic UserController(UserDao userDao) {this.userDao = userDao;}// Setter 方法注入private AnotherService anotherService;@Autowiredpublic void setAnotherService(AnotherService anotherService) {this.anotherService = anotherService;}
}

@Autowired 可以用于字段、构造函数和 Setter 方法,默认按类型进行自动装配。如果存在多个相同类型的 Bean,可能会出现注入歧义,需要结合 @Qualifier 注解使用。

2. @Qualifier
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;@Component
public class UserController {@Autowired@Qualifier("specificUserService")private UserService userService;// 其他代码
}

当存在多个相同类型的 Bean 时,@Qualifier 用于指定要注入的 Bean 的名称,解决注入歧义问题。

3. @Resource
import javax.annotation.Resource;
import org.springframework.stereotype.Component;@Component
public class UserController {// 按名称注入@Resource(name = "userService")private UserService userService;// 按类型注入@Resourceprivate UserDao userDao;
}

@Resource 是 JSR - 250 规范中的注解,默认按名称注入,如果未指定名称,则按类型注入。

4. @Inject
import javax.inject.Inject;
import org.springframework.stereotype.Component;@Component
public class UserController {@Injectprivate UserService userService;// 其他代码
}

@Inject 是 JSR - 330 规范中的注解,功能和 @Autowired 类似,用于依赖注入。

配置类注解

这些注解用于通过 Java 代码定义 Bean 和配置 Spring 容器。

1. @Configuration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserService();}@Beanpublic UserDao userDao() {return new UserDaoImpl();}
}

@Configuration 用于标记一个类为 Java 配置类,该类中的方法可以使用 @Bean 注解定义 Bean。

2. @Bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic UserService userService() {// 可以在这里进行复杂的初始化操作UserService userService = new UserService();userService.setUserDao(userDao());return userService;}@Beanpublic UserDao userDao() {return new UserDaoImpl();}
}

@Bean 注解用于在 @Configuration 类的方法上,方法的返回值会被注册到 Spring 容器中作为一个 Bean。开发者可以在方法中进行复杂的初始化操作。

通过以上这些配置文件和注解方式,Spring 框架提供了丰富多样的手段来实现控制反转和依赖注入,开发者可以根据项目的实际情况灵活选择和组合使用。

相关文章:

  • 怎样利用 macOS 自带功能快速进行批量重命名文件教程
  • 服务器内存规格详解
  • 饭店管理系统(下篇):程序打包为exe给用户使用
  • 2. kubernetes操作概览
  • Gradle相关配置文件的关系、作用及使用方式
  • 【时时三省】(C语言基础)选择结构程序设计习题1
  • Python异步编程入门:Async/Await实战详解
  • vector常用的接口和底层
  • AI对话高阶玩法:解锁模型潜能的实用案例教程
  • 消息中间件面试题
  • 开源TTS项目GPT-SoVITS,支持跨语言合成、支持多语言~
  • java面向对象06:封装
  • cmd 终端输出乱码问题 |Visual Studio 控制台输出中文乱码解决
  • Day08【基于预训练模型分词器实现交互型文本匹配】
  • 考研数据结构之树与二叉树的应用:哈夫曼树、哈夫曼编码与并查集
  • JavaWeb开发 Servlet底层 从概念到HTTP请求 到web服务器再到servlet
  • ROS2 常用
  • How to run ERSEM
  • linux上安装vimplus 从零开始
  • 使用Python构建桌面图片浏览器
  • 全球南方声势卓然壮大的历史逻辑——写在万隆会议召开70周年之际
  • 马上评|机器人马拉松,也是具身智能产业的加速跑
  • 错失两局领先浪费赛点,王楚钦不敌雨果无缘世界杯男单决赛
  • “雪豹瘫痪”“漂流小孩哥大闹幼儿园”都是谣言!10起典型案例公布
  • 郑州一废弃饭店堆砌物起火:明火被扑灭,未造成人员伤亡
  • 是什么,坚定了外资企业“在浦东为世界”的决心?