IoC容器、依赖注入;基于XML && 基于注解 && 基于Java Config配置IoC容器——实例化对象+对象依赖注入;Spring与JUnit4整合
概念
- IoC,Inversion of Control,控制反转:将对象的控制权交由第三方统一管理
- DI,Dependency Injection:依赖注入,使用反射技术,是一种IoC的实现
- Spring IoC容器:用于统一创建与管理对象依赖
- XML管理对象(bean):applicationContext.xml
Spring框架使用流程-基于XML配置IoC容器
1. 导入spring坐标
| <dependency> |
| <groupId>org.springframework</groupId> |
| <artifactId>spring-context</artifactId> |
| <version>5.3.18</version> |
| </dependency> |
2. 创建spring配置文件applicationContext.xml

| <?xml version="1.0" encoding="UTF-8"?> |
| <beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> |
| |
| </beans> |
3. 实例化对象
- XML管理Bean
- Bean id与name都是设置对象在IoC容器中的唯一标识,两者在同一个配置文件中不允许重复出现,在不同的配置文件中可以重复出现,新对象覆盖旧对象。【推荐使用bean id标识对象】,在没有设置bean id和name时,使用类全称作为bean标识。
基于构造方法创建对象
| |
| <bean id="softApple" class="com.EveX.spring.ioc.entity.Apple"> |
| <constructor-arg name="title" value="金帅"></constructor-arg> |
| <constructor-arg name="color" value="黄色"></constructor-arg> |
| <constructor-arg name="origin" value="中国"></constructor-arg> |
| </bean> |
基于静态工厂创建对象(少用,了解)
| |
| <bean id = "sweetApple" class="com.EveX.spring.ioc.factory.AppleFactory" factory-method="creatSweetApple"></bean> |
| |
| package com.EveX.spring.ioc.factory; |
| |
| import com.EveX.spring.ioc.entity.Apple; |
| |
| public class AppleFactory { |
| public static Apple creatSweetApple() { |
| Apple sweetApple = new Apple(); |
| sweetApple.setTitle("红富士"); |
| sweetApple.setColor("红色"); |
| sweetApple.setOrigin("欧洲"); |
| return sweetApple; |
| } |
| } |
| |
基于工厂实例化创建对象(少用,了解)
IoC容器对工厂类进行实例化并调用对应的实例方法创建对象
| |
| <bean id = "factoryInstance" class="com.EveX.spring.ioc.factory.AppleFactoryInstance"></bean> |
| <bean id = "sweetApple" factory-bean="factoryInstance" factory-method="creatSweetApple"></bean> |
| |
| package com.EveX.spring.ioc.factory; |
| |
| import com.EveX.spring.ioc.entity.Apple; |
| |
| public class AppleFactoryInstance { |
| public Apple creatSweetApple() { |
| Apple sweetApple = new Apple(); |
| sweetApple.setTitle("红富士"); |
| sweetApple.setColor("绿色"); |
| sweetApple.setOrigin("欧洲"); |
| return sweetApple; |
| } |
| } |
| |
4. 启动IoC容器
初始化IoC容器并根据XML配置文件实例化对象
| public static void main(String[] args) { |
| ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); |
| |
| } |
路径表达式

其中,类的根路径是:

5. 从IoC容器中获取Bean
| Apple sweetApple = context.getBean("sweetApple", Apple.class); |
6. 依赖注入
利用setter实现对象依赖注入
利用setter实现静态数值注入
- 使用property子标签,利用setter实现对象依赖注入
- 类中需要实现属性的get和set方法,IoC容器自动利用反射机制,运行时调用setXXX()方法为属性赋值
| <bean id="sweetApple" class="com.EveX.spring.ioc.entity.Apple"> |
| <property name="title" value="红富士"></property> |
| <property name="color" value="红色"></property> |
| <property name="origin" value="欧洲"></property> |
| </bean> |
利用setter实现对象注入
| <bean id = "lily" class="com.EveX.spring.ioc.entity.Child"> |
| <property name="name" value="莉莉"></property> |
| <property name="apple" ref="sweetApple"></property> |
| </bean> |
利用构造方法实现对象注入
| <bean id="andy" class="com.EveX.spring.ioc.entity.Child"> |
| <constructor-arg name="name" value="安迪"></constructor-arg> |
| <constructor-arg name="apple" ref="softApple"></constructor-arg> |
| </bean> |
注入集合对象
注入List(默认ArrayList)

注入Set(默认LinkedHashSet-数据有序)

注入Map(默认LinkedHashMap-数据有序)

注入 Properties
使用键值对(key-value pairs)的形式来存储数据,但要求key和value都是字符串类型

获取容器内对象
- 使用getBeanDefinitionNames方法获取所有的bean id,然后通过bean id获取每一个bean对象
| String[] beanDefinitionNames = context.getBeanDefinitionNames(); |
| for (String beanDefinitionName : beanDefinitionNames) { |
| System.out.println(beanDefinitionName); |
| System.out.println(context.getBean(beanDefinitionName)); |
| } |
bean scope属性
| <bean id="..." class="..." scope="prototype"> |
- bean scope属性用于决定对象何时被创建与其作用范围
- bean scope会影响容器中对象的数量
- 默认情况下,bean会在IoC容器创建后自动实例化,且全局唯一

- singleton:在IoC容器中,singleton是单例多线程执行,存在线程安全问题
- prototype:多实例,占用更多资源,不存在线程安全问题

bean生命周期

其中,init-method和destroy-method都是bean的一个子字段,保证其对应的方法名和类的方法相对应即可,在生命周期中会进行执行
Spring框架使用流程-基于注解配置IoC容器
四种组件类型注解

- 组件类型注解默认bean id为首字母小写的类名
- 对于不好分类的类,则使用Component注解
初始化IoC容器
- 在IoC容器初始化时,自动扫描四种组件类型注解并完成实例化
XML配置开启组件扫描
- 比XML配置IoC容器多一行
xmlns:context="http://www.springframework.org/schema/context"
| <?xml version="1.0" encoding="UTF-8"?> |
| <beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xmlns:context="http://www.springframework.org/schema/context" |
| xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> |
| |
| <context:component-scan base-package="com.EveX"> |
| </beans> |
两类自动装配注解

- 如果装配注解放在set方法上,则自动按类型/名称对set方法参数进行注入
- 如果放在属性上,IoC容器会自动通过反射技术将属性private修饰符自动改为public,直接进行赋值,赋值完成后再改为pribate,不会执行set方法。
- 不建议使用按类型注入,如果给一个接口按类型装配,那么其所有实现类都是同类型bean,注入过程会出现问题
@Resource
- 设置了name属性,则直接按照name在IoC容器中将bean注入
- 未设置name属性
(1)首先以属性名作为bean name在IoC容器中匹配bean,如果匹配到了则注入
(2)如果未匹配,则按照类型进行匹配(同@Autowired),如果有冲突,加@Primary注解解决
- 建议:设置name属性 || 保证属性名与bean name一致
元数据注解

通知IoC容器初始化时加载属性文件
| <context:property-placeholder location="classpath:config.properties"></context:property-placeholder> |
@Value
-
新增配置文件
config.properties

-
添加@Value注解

Spring框架使用流程-基于Java Config配置IoC容器
Java Config核心注解

Java Config对象实例化
- 增加配置类Config.java
(1)添加@Configuration注解,表示当前类是一个配置类,用于替代applicationContext.xml配置文件
(2)添加@Bean注解,Java Config利用方法创建对象,将方法返回的对象放入容器,bean id=方法名
| @Configuration |
| public class Config { |
| @Bean |
| public Apple sweetApple() { |
| return new Apple(); |
| } |
| } |
| |
- 程序入口
| AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); |
Java Config 对象依赖注入
将依赖的对象作为参数传入方法中,对象名作为bean id在容器中存在则直接匹配,如果不存在则进行类型匹配
| @Configuration |
| public class Config { |
| @Bean |
| public Apple sweetApple() { |
| return new Apple(); |
| } |
| |
| @Bean |
| public Child lily(Apple sweetApple) { |
| Child child = new Child(); |
| child.setApple(sweetApple); |
| return child; |
| } |
| } |
Spring与JUnit4整合
- 添加spring-test(确保和spring-context版本一致)和junit的依赖
| <dependency> |
| <groupId>org.springframework</groupId> |
| <artifactId>spring-test</artifactId> |
| <version>5.3.18</version> |
| </dependency> |
| |
| <dependency> |
| <groupId>junit</groupId> |
| <artifactId>junit</artifactId> |
| <version>4.12</version> |
| <scope>test</scope> |
| </dependency> |
-
在测试类上添加@RunWith和@ContextConfiguration注解,将Junit4的执行权交由Spring Test,在测试用例执行前自动初始化IoC容器
-
在测试类中加入需要测试的属性
-
写测试方法
| @RunWith(SpringJUnit4ClassRunner.class) |
| @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) |
| public class SpringTest { |
| @Resource |
| private Child andy; |
| |
| @Test |
| public void testAndy() { |
| andy.eat(); |
| } |
| } |
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
· 全程使用 AI 从 0 到 1 写了个小工具