Spring03——基于xml的Spring应用
Spring开发中主要对Bean的配置
Bean的常用配置一览如下:
Xml配置方式 | 功能描述 |
---|---|
<bean id="" class=""> | Bean的id和全限定名配置 |
<bean name=""> | 通过name设置Bean的别名,通过别名也能直接获取到Bean实例 |
<bean scope=""> | Bean的作用范围,BeanFactory作为容器时取值singleton和prototype |
<bean lazy-init=""> | Bean的实例化时机,是否延迟加载。BeanFactory作为容器时无效 |
<bean init-method=""> | Bean实例化后自动执行的初始化方法,method指定方法名 |
<bean destroy-method=""> | Bean实例销毁前的方法,method指定方法名 |
<bean autowire="byType"> | 设定自动注入模式,常用的有按类型byType,按名称byName |
<bean factory-bean="" factory-method=""/> | 指定哪个工厂Bean的哪个方法来完成Bean的创建 |
Bean取别名
通过name取别名,同样可以获取实例
Bean的范围配置
默认情况下,单纯的Spring环境Bean的作用范围有两个(scope配置):Singleton和Prototype
- singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例;
- prototype(默认):原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。
Bean的延迟加载
当lazy-init设置为true时为延迟加载,也就是当Spring容器创建的时候,不会立即创建Bean实例,等待用到时在创建Bean实例并存储到单例池中去,后续在使用该Bean直接从单例池获取即可,本质上该Bean还是单例的
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" lazy-init="true"/>
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");// lazy-init="true"开启,那么只有调用getBean时才会创建Bean实例,而不是之前创建容器时UserService userService = (UserService) applicationContext.getBean("aaa");System.out.println(userService);
Bean的初始化和销毁方法配置
Bean在被实例化后,可以通过指定的初始化方法完成一些初始化的操作,Bean在销毁之前也可以执行指定的销毁方法完成一些操作。
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"init-method="init" destroy-method="destroy"/>
定义init方法和destory方法
public class UserDaoImpl implements UserDao { public UserDaoImpl() { System.out.println("UserDaoImpl创建了..."); } public void init() { System.out.println("初始化方法..."); } public void destroy() { System.out.println("销毁方法..."); }
}
由上图可见,并没有显示销毁方法
关闭容器Bean就销毁,否则bean销毁不了,因为关闭容器是在虚拟机结束之前执行,如果没有close,那么虚拟机关闭,什么都没有了。
扩展:除此之外,我们还可以通过实现 InitializingBean 接口,完成一些Bean的初始化操作,如下:
public class UserDaoImpl implements UserDao, InitializingBean { public UserDaoImpl() { System.out.println("UserDaoImpl创建了..."); } public void init() { System.out.println("初始化方法..."); } public void destroy() { System.out.println("销毁方法..."); } // 执行时机早于init-method配置的方法 @Overridepublic void afterPropertiesSet() throws Exception { System.out.println("InitializingBean..."); }
}
使用InitializingBean , DisposableBean接口(推荐)
这样就不需要再Bean标签里写init和destory了
Bean的生命周期
下面是Spring Bean生命周期示例,包括创建、初始化和销毁的代码。
Bean类
创建一个简单的Bean类,并定义初始化和销毁方法:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.DisposableBean; public class MyBean implements InitializingBean, DisposableBean { private String name; private String version; private String author; public MyBean() { System.out.println("1. 创建对象 - 构造器"); } public void setName(String name) { this.name = name; System.out.println("设置属性 - name: " + name); } public void setVersion(String version) { this.version = version; System.out.println("设置属性 - version: " + version); } public void setAuthor(String author) { this.author = author; System.out.println("设置属性 - author: " + author); } @Override public void afterPropertiesSet() throws Exception { System.out.println("4. 执行Bean初始化方法 (afterPropertiesSet)"); System.out.println("Bean 信息 - Name: " + name + ", Version: " + version + ", Author: " + author); } @Override public void destroy() throws Exception { System.out.println("关停 Bean - 销毁方法 (destroy)"); } public void performTask() { System.out.println("执行业务操作 - " + name); }
}
Spring配置
使用XML配置来定义Bean,指定其由接口管理的初始化和销毁方法:
<bean id="myBean" class="com.example.MyBean"> <property name="name" value="Spring Bean"/> <property name="version" value="1.0"/> <property name="author" value="John Doe"/> </bean>
主程序
创建Application
类,加载Spring上下文,使用Bean并关闭上下文以触发销毁阶段:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyBean myBean = (MyBean) context.getBean("myBean"); // 执行myBean的一些业务// 关闭上下文,触发销毁方法 ((ClassPathXmlApplicationContext) context).close(); }
}
Bean的3种实例化
构造方式实例化:底层通过构造方法对Bean进行实例化
工厂方式实例化:底层通过调用自定义的工厂方法对Bean进行实例化
Bean的实例化配置
构造方式实例化Bean又分为无参构造方法实例化和有参构造方法实例化,Spring中配置的<bean>
几乎都是无参构造方式,但处不在赘述。下面讲解有参构造方法实例化Bean
// 有参构造方法
public UserDaoImpl(String name){
}
在实现类文件里默认有一个无参构造器,如果写一个有参构造器,那么jvm识别不到无参构造器会报错 。
在实现类文件中写入有参构造方法后,有参构造在实例化Bean时,需要参数的注入,通过<constructor-arg>
标签(name表示传入的变量名,value表示变量名对应的传入参数,在bean标签里传入即可,调用getBean会自动添加进去,如果有多个参数,就多个<constructor-arg>标签
),嵌入在<bean>
标签内部提供构造参数,如下:
<!--上面的有参构造器对应的xml配置-->
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"> <constructor-arg name="name" value="haohao"/>
</bean>
静态工厂创建对象
factory-method 创建对象:即在xml的bean标签里配置factory-method = "userDao",那么创建getBean对象返回的不是class对应的类的实例,而是class类里面userDao静态方法返回的实例
<bean id="userDao1" class="com.itheima.factory.MyBeanFactory1"factory-method="userDao"></bean>
public class MyBeanFactory1 {public static UserDao userDao(){// bean之前可以进行其他的业务逻辑操作return new UserDaoImpl();}
}
实例工厂创建对象
<--实例化一个工厂-->
<bean id="myBeanFactory2" class="com.itheima.factory.MyBeanFactory2"lazy-init="true"></bean>
<--factory-bean是代指工厂-->
<bean id="userDao2" factory-bean="myBeanFactory2"
factory-method="userDao" lazy-init="true"></bean>
public class MyBeanFactory2 {
// 实例方法返回对象public UserDao userDao(){return new UserDaoImpl();}
}
FactoryBean创建(实用)
package com.itheima.factory;import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;public class UserDaoFactoryBean implements FactoryBean {// 返回bean@Overridepublic UserDao getObject() throws Exception {return new UserDaoImpl();}// 返回Bean的类型@Overridepublic Class<?> getObjectType() {return UserDao.class;}
// 是否为单例@Overridepublic boolean isSingleton() {return true;}
}
<bean id="UserDao" class="com.itheima.factory.UserDaoFactoryBean"></bean>
依赖注入的方式
一、setter方法注入引用类型/简单类型(下面以同时注入这两种类型为例)
假设我们有一个Product
类,它包含一个简单类型属性(如productId
)和一个引用类型属性(如Category
)。
1. 定义Category
类
首先,定义Category
类,表示产品类别:
public class Category { private String categoryName; // Setter方法 public void setCategoryName(String categoryName) { this.categoryName = categoryName; } // Getter方法 public String getCategoryName() { return categoryName; } public void displayInfo() { System.out.println("Category: " + categoryName); }
}
2. 定义Product
类
接下来,定义一个Product
类,它具有一个简单类型的productId
和一个引用类型的Category
:
public class Product { private String productId; // 简单类型 private Category category; // 引用类型 // Setter方法注入 public void setProductId(String productId) { this.productId = productId; } public void setCategory(Category category) { this.category = category; } public void displayProductInfo() { System.out.println("Product ID: " + productId); if (category != null) { category.displayInfo(); } else { System.out.println("No category information available."); } }
}
3. Spring配置文件
在Spring的XML配置文件中,定义Category
和Product
的Bean,并同时注入简单类型和引用类型:
<!-- applicationContext.xml -->
<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"> <bean id="category" class="com.example.Category"> <property name="categoryName" value="Electronics"/> <!-- 注入简单类型 --> </bean> <bean id="product" class="com.example.Product"> <property name="productId" value="P12345"/> <!-- 注入简单类型name是形参 --> <property name="category" ref="category"/> <!-- 注入引用类型 --> </bean>
</beans>
4. 主程序
最后,创建一个主程序,通过Spring上下文来获取Product
对象并执行相应操作:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { // 加载Spring上下文 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取product Bean Product product = (Product) context.getBean("product"); product.displayProductInfo(); // 显示产品信息 // 关闭上下文 ((ClassPathXmlApplicationContext) context).close(); }
}
运行结果
运行程序将输出以下内容:
Product ID: P12345
Category: Electronics
二、构造器注入引用类型/简单类型(下面以同时注入这两种类型为例)
1. 定义Category
类
Category
类保持不变,依然表示产品类别
2. 定义Product
类
将Product
类的构造函数修改为接收两个参数:一个简单类型productId
和一个引用类型Category
。
public class Product { private String productId; // 简单类型 private Category category; // 引用类型 // 构造函数注入 public Product(String productId, Category category) { this.productId = productId; this.category = category; } public void displayProductInfo() { System.out.println("Product ID: " + productId); if (category != null) { category.displayInfo(); } else { System.out.println("No category information available."); } }
}
3. Spring配置文件
在Spring的XML配置文件中,使用构造器来注入简单类型和引用类型。我们可以使用constructor-arg
来指定构造函数参数:
<!-- applicationContext.xml -->
<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"> <bean id="category" class="com.example.Category"> <property name="categoryName" value="Electronics"/> <!-- 注入简单类型 --> </bean> <bean id="product" class="com.example.Product"> <constructor-arg value="P12345"/> <!-- 注入简单类型 --> <constructor-arg ref="category"/> <!-- 注入引用类型 --> </bean>
</beans>
4. 主程序
主程序实例保持不变,只是调用已经不同的注入手段(构造器)来获取Product
对象并执行操作
- 强制依赖使用构造器进行,使用setter注入有概率不进行时导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以同时使用,使用构造器注入完全依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中需要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
依赖自动装配
- 自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配时(byType)必须保证容器中相同类型的bean唯一,推荐使用
- 使用按名称装配时(byName)必须保证容器中具有指定名称的bean,因为变量名与配置混合,不推荐使用
- 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
集合的注入
<!-- 定义一个bean,id为bookDao,对应的实现类为com.itheima.dao.impl.BookDaoImpl -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"><!-- 配置一个名为array的属性,类型为数组 --><property name="array"><!-- 数组元素 --><array><!-- 数组中的值 --><value>100</value><value>200</value><value>300</value></array></property><!-- 配置一个名为list的属性,类型为列表 --><property name="list"><!-- 列表元素 --><list><!-- 列表中的值 --><value>itcast</value><value>itheima</value><value>boxuegu</value><value>chuanzhihui</value></list></property><!-- 配置一个名为set的属性,类型为集合 --><property name="set"><!-- 集合元素 --><set><!-- 集合中的值,注意集合不允许重复值 --><value>itcast</value><value>itheima</value><value>boxuegu</value><!-- 重复的值boxuegu将被忽略 --><value>boxuegu</value></set></property><!-- 配置一个名为map的属性,类型为映射 --><property name="map"><!-- 映射元素 --><map><!-- 映射中的键值对 --><entry key="country" value="china"/><!-- 可以继续添加更多的键值对 --></map></property>
</bean>
相关文章:

Spring03——基于xml的Spring应用
Spring开发中主要对Bean的配置 Bean的常用配置一览如下: Xml配置方式功能描述<bean id"" class"">Bean的id和全限定名配置<bean name"">通过name设置Bean的别名,通过别名也能直接获取到Bean实例<bean sc…...
【AIGC半月报】AIGC大模型启元:2024.12(上)
【AIGC半月报】AIGC大模型启元:2024.12(上) (1)OpenAI-12日发布会(持续更新中........)Day01-12.06:SoraDay02-12.07:ChatGPT圣诞老人风格的语音Day03-12.08:…...
本etcd系列文章补充说明
最开始今年四月份读的是etcdv3.6的main分支的代码,最开始没注意,main分支代码是不断修改的,并且最开始对etcd不太了解,所以源码笔记有些理解不太准确,也可能略有错误,所以年底就回过头来重新复习一遍&#…...

【新品发布】ESP32-P4开发板 —— 启明智显匠心之作,为物联网及HMI产品注入强劲动力
核心亮点: ESP32-P4开发板,是启明智显精心打造的一款高性能物联网开发板。它专为物联网项目及HMI(人机界面)产品而设计,旨在为您提供卓越的性能和稳定可靠的运行体验。 强大硬件配置: 双核400MHz RISC-V处…...

HTML 添加 文本水印
body,html {margin: 0;height: 100vh;width: 100vw;} // 自定义文案const setting {text: "水印文案", // 水印内容innerDate: true, // 在水印下方增加日期width: 110, // 水印宽度};// 自定义文字水印const watermark (function () {return {build: function (a…...

软件无线电安全之GNU Radio基础(下)
往期回顾 软件无线电安全之GUN Radio基础(上) 背景 在上一小节中,我们简单介绍和使用了GNU Radio软件的基础功能和模块,同时通过GNU Radio Companion(GRC)创建了简单的流程图,展示了信号生成、处理和输出的流程。最后…...
windows基础
系统目录 服务 端口 注册表 黑客常用DOS命令(在拿到shell时会用到) 一、 系统目录 Windows目录 系统的安装目录 System32configSAM文件 是用户密码的存储文件 System32etchost文件 记录本地解析(优先级大于DNS域名解析)可以自…...

hhdb数据库介绍(10-43)
安全 密码安全管理 密码安全管理为用户提供了对计算节点数据库用户与存储节点的连接用户、备份用户的密码有效期监控提醒。到期后自动提示用户修改密码以提升系统的安全性。 数据库用户密码 (一)密码修改 用户可以在“安全->密码安全管理->数据…...
JMS和消息中间件:Kafka/RocketMQ
文章目录 消息传递模型使用JMS还是KafkaKafka与RocketMQ的优缺点Kafka与RocketMQ的使用场景Kafka与RocketMQ的选型指南 TPM 项目中, iflow之间使用了JMS,后端项目与数据库通信使用Kafka MQ和JMS的区别: JMS是 java 用来处理消息的一个API规范…...

【问题解决】ArcgisGP工具使用GIS模块自动发布图层报错:过渡失败
项目场景: 使用Arcpy脚本发布GP工具服务,该工具结果生成一个矢量文件,并且需要自动发布成在线图层,脚本中已经包含了自动发布图层的代码,本地在ArcgisPro中执行成功。现在需要将该工具发布成web工具。 问题描述 在…...
Yocto bitbake and codeSonar
1 mdm 1.1 屏蔽mdm sysvinit的console输出 - uboot传入参数的时候传入consolenull,这样Linux启动信息没有了 - 还需要在Linux配置中去掉Support for console on AMBA serial port - 文件系统/etc/inittab文件里注释掉::respawn:/sbin/getty -L ttyS000 115200 vt100…...

gpt-computer-assistant - 极简的 GPT-4o 客户端
更多AI开源软件: AI开源 - 小众AIhttps://www.aiinn.cn/sources gpt-computer-assistant是一个将 ChatGPT MacOS 应用程序提供给 Windows 和 Linux 的替代工作。因此,这是一个全新且稳定的项目。此时,您可以轻松地将其作为 Python 库安装&am…...

中国移动量子云平台:算力并网590量子比特!
在技术革新的浪潮中,量子计算以其独特的并行处理能力和指数级增长的计算潜力,有望成为未来技术范式变革和颠覆式创新应用的新源泉。中国移动作为通信行业的领军企业,致力于量子计算技术研究,推动量子计算产业的跨越式发展。 量子云…...
Vue 3 中的计算属性(Computed Properties)详解
目录 Vue 3 中的计算属性(Computed Properties)详解 引言 什么是计算属性? 创建和使用计算属性 示例 1:基本用法 示例 2:带有 getter 和 setter 的计算属性 计算属性 vs 方法 Vue 3 中的计算属性(Co…...
AWS S3 权限配置与文件上传下载指南
本文介绍如何配置 AWS S3 存储桶的访问权限,实现 EC2 实例上传文件和本地用户下载文件的功能。 权限配置 © ivwdcwso (ID: u012172506) 1. EC2 角色上传权限 创建 IAM 角色并附加以下策略,允许 EC2 实例上传文件到 S3: {"Version": "2012-10-17&qu…...

6. 一分钟读懂“抽象工厂模式”
6.1 模式介绍 书接上文,工厂方法模式只能搞定单一产品族,遇到需要生产多个产品族时就歇菜了。于是,在需求的“花式鞭策”下,程序员们再次绷紧脑细胞,创造出了更强大的抽象工厂模式,让工厂一次性打包多个产品…...

CV(2)-插值和卷积
前言 仅记录学习过程,有问题欢迎讨论 看看年前可以学到哪。 频率: 灰度值变化程度的指标,是灰度再平面上的梯度幅值: 幅值: 是在一个周期内,交流电瞬时出现的最大绝对值,也是一个正弦波,波…...

学习threejs,通过设置纹理属性来修改纹理贴图的位置和大小
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️Texture 贴图 二、…...

fastadmin 后台插件制作方法
目录 一:开发流程 二:开发过程 (一):后台功能开发 (二):功能打包到插件目录 (三):打包插件 (四):安装插件…...

9. 一分钟读懂“策略模式”
9.1 模式介绍 策略模式是一种行为型设计模式,用于在运行时灵活切换对象的行为或算法,它将算法封装为独立的类,使得它们可以互相替换,而不会影响使用这些算法的客户端代码。 策略模式的核心思想是:定义一系列可互换的算…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...