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

手写Spring第7弹:Spring IoC容器深度解析:XML配置的完整指南

  1. Spring IoC容器深度解析:XML配置的完整指南

  2. XML配置的艺术:掌握Spring Bean管理的精髓

  3. 从Bean定义到生命周期:Spring IoC的XML配置全解

  4. Spring XML配置进阶:作用域、生命周期与依赖注入

  5. 深入Spring IoC:XML配置的原理与实践


Spring IoC容器深度解析:XML配置的完整指南

引言:XML配置在Spring中的核心地位

在Spring框架的发展历程中,XML配置曾经是IoC容器配置的主要方式,至今仍在许多传统企业级项目中广泛使用。理解XML配置不仅有助于维护遗留系统,更是深入掌握Spring IoC原理的重要途径。XML配置通过声明式的方式描述Bean之间的关系,将对象的创建、依赖注入和生命周期管理从代码中解耦出来,体现了"配置与代码分离"的设计哲学。

本文将深入剖析Spring IoC容器的XML配置机制,从基础的Bean定义到高级的生命周期管理,带你全面掌握XML配置的精髓。通过理解这些底层原理,你不仅能够熟练使用XML配置,更能为后续学习注解配置和Java配置打下坚实的基础。

目录

Spring IoC容器深度解析:XML配置的完整指南

引言:XML配置在Spring中的核心地位

一、Bean定义基础: 标签深度解析

1.1 Bean的核心属性

1.2 Bean命名与别名的区别

二、Bean作用域:控制实例化策略

2.1 Singleton作用域(默认)

2.2 Prototype作用域

2.3 其他作用域

三、依赖注入:XML配置的核心功能

3.1 构造器注入

3.2 Setter方法注入

3.3 复杂类型注入

四、Bean生命周期:从创建到销毁的完整过程

4.1 完整的生命周期阶段

4.2 生命周期回调的执行顺序

五、高级配置技巧

5.1 继承配置

5.2 工厂方法创建Bean

5.3 使用p命名空间简化配置

六、实际应用案例

6.1 完整的数据访问层配置

七、最佳实践与常见陷阱

7.1 配置最佳实践

7.2 常见问题与解决方案

结语:XML配置的价值与演进


  🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我。文末有免费源码

免费获取源码。

更多内容敬请期待。如有需要可以联系作者免费送

更多源码定制,项目修改,项目二开可以联系作者
点击可以进行搜索(每人免费送一套代码):千套源码目录(点我)

2025元旦源码免费送(点我)

我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。

一、Bean定义基础:<bean>标签深度解析

1.1 Bean的核心属性

在Spring的XML配置中,<bean>标签是最基本的配置单元,每个<bean>标签都描述了一个由Spring容器管理的对象。

 <bean id="userService" name="service,userManager"class="com.example.UserServiceImpl"scope="singleton"lazy-init="false"init-method="init"destroy-method="cleanup"autowire="byName"></bean>

属性详解

  • id:Bean的唯一标识符,在同一个Spring容器中必须唯一

  • name:Bean的别名,可以用逗号分隔多个别名

  • class:Bean的完整类名,Spring通过反射实例化该类

  • scope:Bean的作用域,控制Bean的实例化策略

  • lazy-init:是否延迟初始化,默认false(容器启动时立即创建)

  • init-method:初始化回调方法名

  • destroy-method:销毁回调方法名

  • autowire:自动装配模式

1.2 Bean命名与别名的区别

id与name的异同

  • id:必须符合XML ID命名规范(不能以数字开头,不能包含特殊字符)

  • name:命名更灵活,可以包含任何字符,支持多个别名

 <!-- 使用id和name的组合 --><bean id="primaryUserService" name="userService, us, userManager"class="com.example.UserServiceImpl"></bean>

在代码中可以通过任意一个名称获取Bean:

 UserService service1 = (UserService) context.getBean("primaryUserService");UserService service2 = (UserService) context.getBean("userService");UserService service3 = (UserService) context.getBean("us");

二、Bean作用域:控制实例化策略

2.1 Singleton作用域(默认)

Singleton是默认的作用域,在整个Spring容器中,一个Bean定义只对应一个实例。

 <bean id="singletonService" class="com.example.SingletonService"scope="singleton"></bean>

特性

  • 容器启动时创建实例(除非设置lazy-init="true")

  • 所有对该Bean的请求都返回同一个实例

  • 适合无状态的Bean,如Service、DAO等

内存模型

 容器中:singletonService → 同一个SingletonService实例所有引用都指向同一个内存地址
2.2 Prototype作用域

每次请求都会创建一个新的Bean实例。

 <bean id="prototypeService" class="com.example.PrototypeService"scope="prototype"></bean>

特性

  • 每次调用getBean()时创建新实例

  • 容器不管理Prototype Bean的完整生命周期

  • 适合有状态的Bean,如每次请求需要独立状态的Bean

内存模型

 容器中:prototypeService → PrototypeService工厂每次getBean()返回新的内存地址
2.3 其他作用域

在Web应用中还有更多作用域:

 <bean id="requestBean" scope="request"><bean id="sessionBean" scope="session"><bean id="applicationBean" scope="application"><bean id="websocketBean" scope="websocket">

三、依赖注入:XML配置的核心功能

3.1 构造器注入

通过构造函数参数注入依赖:

<bean id="userService" class="com.example.UserService"><constructor-arg index="0" value="admin"/><constructor-arg index="1" ref="userRepository"/><constructor-arg index="2"><list><value>权限1</value><value>权限2</value></list></constructor-arg>
</bean>

构造器参数配置方式

  • index:参数索引位置(从0开始)

  • type:参数类型

  • name:参数名称(需要调试信息)

3.2 Setter方法注入

通过setter方法注入依赖:

<bean id="dataSource" class="com.example.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test"/><property name="username" value="root"/><property name="password" value="123456"/><property name="connectionProperties"><props><prop key="useUnicode">true</prop><prop key="characterEncoding">UTF-8</prop></props></property>
</bean>
3.3 复杂类型注入

Spring支持各种复杂数据类型的注入:

<bean id="complexBean" class="com.example.ComplexBean"><!-- List注入 --><property name="stringList"><list><value>value1</value><value>value2</value><value>value3</value></list></property><!-- Set注入 --><property name="stringSet"><set><value>setValue1</value><value>setValue2</value></set></property><!-- Map注入 --><property name="stringMap"><map><entry key="key1" value="value1"/><entry key="key2" value="value2"/></map></property><!-- Properties注入 --><property name="properties"><props><prop key="prop1">value1</prop><prop key="prop2">value2</prop></props></property>
</bean>

四、Bean生命周期:从创建到销毁的完整过程

4.1 完整的生命周期阶段

Spring Bean的生命周期包含多个阶段,每个阶段都有相应的回调机制:

<bean id="lifecycleBean" class="com.example.LifecycleBean"init-method="customInit" destroy-method="customDestroy">
</bean>

对应的Java类:

public class LifecycleBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {private String beanName;// 1. 构造函数public LifecycleBean() {System.out.println("1. 构造函数执行");}// 2. BeanNameAware接口@Overridepublic void setBeanName(String name) {this.beanName = name;System.out.println("2. BeanNameAware: " + name);}// 3. BeanFactoryAware接口@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("3. BeanFactoryAware");}// 4. ApplicationContextAware接口@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("4. ApplicationContextAware");}// 5. 属性注入后public void setSomeProperty(String value) {System.out.println("5. 属性注入: " + value);}// 6. InitializingBean接口@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("6. InitializingBean.afterPropertiesSet");}// 7. 自定义init方法public void customInit() {System.out.println("7. 自定义init方法");}// 8. Bean就绪,可被使用// 9. DisposableBean接口@Overridepublic void destroy() throws Exception {System.out.println("9. DisposableBean.destroy");}// 10. 自定义destroy方法public void customDestroy() {System.out.println("10. 自定义destroy方法");}
}
4.2 生命周期回调的执行顺序

通过上面的示例,我们可以看到完整的执行顺序:

  1. 实例化阶段:调用构造函数

  2. Aware接口回调:BeanNameAware → BeanFactoryAware → ApplicationContextAware

  3. 属性注入:调用setter方法注入依赖

  4. 初始化前:BeanPostProcessor.postProcessBeforeInitialization

  5. 初始化回调:InitializingBean.afterPropertiesSet

  6. 自定义初始化:init-method指定的方法

  7. 初始化后:BeanPostProcessor.postProcessAfterInitialization

  8. Bean就绪:Bean可以被使用

  9. 销毁阶段:DisposableBean.destroy → destroy-method

五、高级配置技巧

5.1 继承配置

Bean定义支持继承,可以复用公共配置:

<!-- 抽象父Bean,不会被实例化 -->
<bean id="abstractDataSource" abstract="true"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="maxActive" value="20"/><property name="maxWait" value="10000"/>
</bean><!-- 子Bean继承父Bean配置 -->
<bean id="devDataSource" parent="abstractDataSource"class="com.example.BasicDataSource"><property name="url" value="jdbc:mysql://dev:3306/test"/><property name="username" value="dev_user"/>
</bean><bean id="prodDataSource" parent="abstractDataSource"class="com.example.BasicDataSource"><property name="url" value="jdbc:mysql://prod:3306/test"/><property name="username" value="prod_user"/>
</bean>
5.2 工厂方法创建Bean

对于不能直接通过构造函数创建的类,可以使用工厂方法:

<!-- 静态工厂方法 -->
<bean id="staticFactoryBean"class="com.example.StaticFactory"factory-method="createInstance"><constructor-arg value="参数"/>
</bean><!-- 实例工厂方法 -->
<bean id="instanceFactory" class="com.example.InstanceFactory"/>
<bean id="factoryCreatedBean"factory-bean="instanceFactory"factory-method="createBean"><constructor-arg value="参数"/>
</bean>
5.3 使用p命名空间简化配置

p命名空间可以简化property配置:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 传统方式 --><bean id="traditional" class="com.example.DataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost/test"/><property name="username" value="root"/></bean><!-- 使用p命名空间 --><bean id="simplified" class="com.example.DataSource"p:driverClassName="com.mysql.jdbc.Driver"p:url="jdbc:mysql://localhost/test"p:username="root"/><!-- 引用其他Bean --><bean id="service" class="com.example.UserService"p:userDao-ref="userDao"/>
</beans>

六、实际应用案例

6.1 完整的数据访问层配置
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 数据源配置 --><bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"destroy-method="close"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/spring_demo"/><property name="username" value="root"/><property name="password" value="password"/><property name="initialSize" value="5"/><property name="maxTotal" value="20"/><property name="maxIdle" value="10"/><property name="minIdle" value="5"/></bean><!-- 事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- JdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><!-- DAO层Bean --><bean id="userDao" class="com.example.dao.UserDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate"/></bean><!-- Service层Bean --><bean id="userService" class="com.example.service.UserServiceImpl"><property name="userDao" ref="userDao"/><property name="transactionManager" ref="transactionManager"/></bean><!-- Controller层Bean (prototype作用域) --><bean id="userController" class="com.example.controller.UserController"scope="prototype"><property name="userService" ref="userService"/></bean>
</beans>

七、最佳实践与常见陷阱

7.1 配置最佳实践
  1. 命名规范:Bean的id使用驼峰命名法,清晰表达其职责

  2. 配置组织:大型项目按模块拆分多个配置文件

  3. 版本控制:配置文件与代码一起纳入版本管理

  4. 注释文档:在XML中添加详细注释说明配置用途

7.2 常见问题与解决方案

问题1:循环依赖

<!-- Bean A 依赖 Bean B -->
<bean id="beanA" class="com.example.BeanA"><property name="beanB" ref="beanB"/>
</bean><!-- Bean B 依赖 Bean A -->
<bean id="beanB" class="com.example.BeanB"><property name="beanA" ref="beanA"/>
</bean>

解决方案

  • 使用setter注入而非构造器注入

  • 重构设计,消除循环依赖

  • 使用@Lazy注解延迟初始化

问题2:Bean覆盖 当存在同名Bean时,后定义的会覆盖先定义的,可能导致难以发现的bug。

问题3:资源泄漏 对于需要显式释放资源的Bean,务必配置destroy-method。

结语:XML配置的价值与演进

虽然现代Spring开发更倾向于使用注解和Java配置,但XML配置仍然有其不可替代的价值:

  1. 集中管理:所有配置集中在一个或几个文件中,便于管理

  2. 运行时修改:可以在不重新编译代码的情况下修改配置

  3. 解耦彻底:配置与代码完全分离

  4. 历史项目维护:大量现有项目仍使用XML配置

理解XML配置的底层原理,有助于我们更好地理解Spring IoC容器的工作机制。无论是使用XML、注解还是Java配置,其背后的IoC原理和依赖注入思想都是相通的。

掌握XML配置,就像掌握了Spring的"母语",能够让你在遇到复杂配置问题时游刃有余,也为学习更高级的Spring特性奠定坚实的基础。


🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我。文末有免费源码

💖学习知识需费心,
📕整理归纳更费神。
🎉源码免费人人喜,
🔥码农福利等你领!

💖常来我家多看看,
📕网址:扣棣编程
🎉感谢支持常陪伴,
🔥点赞关注别忘记!

💖山高路远坑又深,
📕大军纵横任驰奔,
🎉谁敢横刀立马行?
🔥唯有点赞+关注成!

往期文章推荐:

基于Springboot + vue实现的学生宿舍信息管理系统
免费获取宠物商城源码--SpringBoot+Vue宠物商城网站系统 
【2025小年源码免费送】

⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇点击此处获取源码⬇⬇⬇⬇⬇⬇⬇⬇⬇

http://www.dtcms.com/a/503528.html

相关文章:

  • java的异常体系
  • pybullet
  • Filebeat、ELK安装与数据同步
  • 嵌入式开发学习日志40——stm32之I2C协议层
  • 网站建设公司小江可以做试题的网站
  • Android 四大组件桥梁 —— Intent (意图) 详解
  • 小鱼在线网站建设网站注册步骤
  • wordpress 视频站模板wordpress和网盘结合
  • Orleans流背压控制机制深度分析
  • Java并发之队列同步器AQS原理
  • c++11可变模版参数 emplace接口 新的类功能 lambda 包装器
  • 手机代码网站有哪些问题吗制作视频特效
  • 济南正规的网站制作郑州做网站九零后网络
  • SQL入门:分页查询核心技术解析
  • 5.3 TCP (答案见原书 P252)
  • 教育房地产 网站建设中山网站建设找丁生
  • 【第十八周】自然语言处理的学习笔记03
  • 探索 Python 判断语句:逻辑与感性的交汇
  • 深圳哪家制作网站好成都近期发生的大事
  • IDEA Gradle并行编译内存溢出问题
  • 如何做电影网站赚钱瓯海住房与城乡建设局网站
  • 婚礼(一)
  • 电阻应变式传感器
  • 在开发过程中遇到问题如何解决,以及两个经典问题
  • 企业网站建设 属于什么费用个人博客网页设计
  • 网站怎么做301信息类网站 wordpress
  • MyBatis入门到精通(Mybatis学习笔记)
  • 一次渗透测试的全过程:从扫描到提权
  • 英语作文网站济南专业做公司网站的机构
  • 织梦后台做的网站怎么绑定域名做瞹视频网站