Spring系列二:基于XML配置bean 中

news/2024/9/15 4:29:36/ 标签: spring, xml, java
xmlns="http://www.w3.org/2000/svg" style="display: none;">

基于XML配置bean

  • 💖使用utillist进行配置
  • 💖属性级联赋值配置
  • 💖通过静态工厂获取bean
  • 💖bean配置信息重用
  • 💖bean创建顺序
  • 💖bean的单例和多实例
  • 💖bean的生命周期

在这里插入图片描述

💖使用utillist进行配置

spring的ioc容器, 可以通过util名称空间来创建list集合

1.新建com.zzw.spring.bean.BookStore

java">public class BookStore {//书private List<String> bookList;//无参构造器, 如果没有其它的构造器, 该无参构造器可以不写//如果有其它的构造器, 则必须显示地定义一下无参构造器public BookStore() {}//getter, setter方法
}

2.src/beans.xml增加如下配置

xml"><!--定义一个util:list, 并且指定了id 可以达到数据复用
说明: 在使用util:list 名称空间的时候, 需要引入相应的标签, 一般来说通过alt+enter会自动加入
, 如果没有就手动添加一下
-->
<util:list id="myBookList"><value>三体</value><value>时间简史</value><value>梦的解析</value><value>福尔摩斯探案集</value>
</util:list><!--配置BookStore对象-->
<bean class="com.zzw.spring.bean.BookStore" id="bookStore"><property name="bookList" ref="myBookList"/>
</bean>

3.测试: com/zzw/spring/test/SpringBeanTest.java新增setBeanByUtilList方法

java">public class SpringBeanTest {//使用util:list名称空间给属性赋值@Testpublic void setBeanByUtilList() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");BookStore bookStore = ioc.getBean("bookStore", BookStore.class);System.out.println("bookStore=" + bookStore);}
}

💖属性级联赋值配置

spring的ioc容器, 可以直接给对象属性的属性赋值, 即级联属性赋值

1.新增com.zzw.spring.bean.Dept部门类

java">public class Dept {private String name;public Dept() {}//getter, setter方法

2.新建com.zzw.spring.bean.Employee员工类

java">public class Employee {private String name;private Dept dept;public Employee() {}//getter, setter方法
}

3.src/beans.xml增加如下配置

xml"><!--配置Dept对象-->
<bean class="com.zzw.spring.bean.Dept" id="dept"/>
<!--配置Employee对象-->
<bean class="com.zzw.spring.bean.Employee" id="employee"><property name="name" value="tom"/><property name="dept" ref="dept"/><!--这里我希望给dept的name属性指定值[级联属性赋值]--><property name="dept.name" value="java开发"/>
</bean>

4.测试: com/zzw/spring/test/SpringBeanTest.java新增setBeanByRelation方法

java">public class SpringBeanTest {//给属性进行级联赋值@Testpublic void setBeanByRelation() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");Employee employee = ioc.getBean("employee", Employee.class);System.out.println("employee=" + employee);}
}

💖通过静态工厂获取bean

spring的ioc容器, 可以通过静态工厂获取bean对象

1.新建com.zzw.spring.factory.MyStaticFactory
这是一个静态工厂类-可以返回Monster对象

java">package com.zzw.spring.factory;public class MyStaticFactory {private static Map<String, Monster> monsterMap;//使用static代码块进行初始化 - java基础static {monsterMap = new HashMap<>();monsterMap.put("monster01", new Monster(100, "齐天大圣", "如意金箍棒"));monsterMap.put("monster02", new Monster(200, "天蓬元帅", "九齿钉耙"));}//提供一个方法, 返回Monster对象public static Monster getMonster(String key) {return monsterMap.get(key);}
}

2.src/beans.xml增加如下配置

xml"><!--配置Monster对象, 通过静态工厂获取
解读
1.通过静态工厂获取bean
2.class 是静态工厂类的全路径
3.factory-method 表示是指定静态工厂类的哪个方法返回对象
4.constructor-arg value="monster02" value是指定要返回静态工厂的哪一个对象
-->
<bean class="com.zzw.spring.factory.MyStaticFactory" id="myMonster01"factory-method="getMonster"><constructor-arg value="monster02"/>
</bean>

3.测试: com/zzw/spring/test/SpringBeanTest.java新增getBeanByStaticFactory方法

java">public class SpringBeanTest {//通过静态工厂获取bean@Testpublic void getBeanByStaticFactory() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");Monster myMonster01 = ioc.getBean("myMonster01", Monster.class);Monster myMonster02 = ioc.getBean("myMonster01", Monster.class);System.out.println("myMonster01=" + myMonster01);System.out.println(myMonster01 == myMonster02);//true. myMonster01和myMonster02是同一个对象}
}

💖bean配置信息重用

spring的ioc容器, 提供了一种继承的方式来实现bean配置信息的重用

1.src/beans.xml增加如下配置

xml"><!--配置Monster对象-->
<bean class="com.zzw.spring.bean.Monster" id="monster10"p:monsterId="10"p:name="蜘蛛侠"p:skill="吐丝"
/>
<!--1.配置Monster对象,2.但是这个对象的属性值和id="monster10"对象的属性值一样3.parent="monster10" 指定当前这个配置的对象的属性值从 id="monster10"的对象来
-->
<bean class="com.zzw.spring.bean.Monster" id="monster11" parent="monster10"/><!--配置Monster对象
1.如果bean指定了 abstract=true, 表示该bean对象, 是用于被继承
2.本身这个bean就不能被获取/实例化
-->
<bean class="com.zzw.spring.bean.Monster" id="monster12" abstract="true"p:monsterId="12"p:name="蜘蛛侠~"p:skill="吐丝~"
/>
<bean id="monster13" class="com.zzw.spring.bean.Monster" parent="monster12"/>

2.测试: com/zzw/spring/test/SpringBeanTest.java新增getBeanByExtends方法

java">public class SpringBeanTest {//通过继承, 配置bean@Testpublic void getBeanByExtends() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");Monster monster11 = ioc.getBean("monster11", Monster.class);System.out.println("monster11=" + monster11);Monster monster13 = ioc.getBean("monster13", Monster.class);System.out.println("monster13=" + monster13);}
}

💖bean创建顺序

spring的ioc容器, 默认是按照配置的顺序创建bean对象

测试bean创建顺序

实验1
1.src/beans.xml增加如下配置

xml"><!--测试bean对象的创建顺序
1.在默认情况下, bean创建的顺序是按照配置顺序来的
2.但是如果我们增加了 depends-on="department01" 这时就会先创建id=department01这个对象
-->
<bean class="com.zzw.spring.bean.Student" id="student01"/>
<bean class="com.zzw.spring.bean.Department" id="department01"/>

2.测试: com/zzw/spring/test/SpringBeanTest.java新增testBeanCreateOrder方法

java">public class SpringBeanTest {@Testpublic void testBeanCreateOrder() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");System.out.println("ok~");}
}

3.新增com.zzw.spring.bean.Department

java">public class Department {public Department() {System.out.println("Department构造器 被执行");}
}

4.新增com.zzw.spring.bean.Student

java">public class Student {public Student() {System.out.println("Student构造器 被执行");}
}

提示: 会先创建student01这个bean对象, 然后创建department01这个bean对象

5.运行结果

java">Student构造器 被执行
Department构造器 被执行
ok~

如果这样配置, 会先创建department01对象, 再创建student01对象

xml"><!--测试bean对象的创建顺序
1.在默认情况下, bean创建的顺序是按照配置顺序来的
2.但是如果我们增加了 depends-on="department01" 这时就会先创建id=department01这个对象
-->
<bean class="com.zzw.spring.bean.Student" id="student01" depends-on="department01"/>
<bean class="com.zzw.spring.bean.Department" id="department01"/>

6.运行结果

java">Department构造器 被执行
Student构造器 被执行
ok~

实验2
1.先看下面的配置, 请问两个bean创建的顺序是什么? 并分析执行流程, src/beans.xml

xml"><!--配置MemberDaoImpl对象-->
<bean class="com.zzw.spring.dao.MemberDaoImpl" id="memberDao"/><bean class="com.zzw.spring.service.MemberServiceImpl" id="memberService"><property name="memberDao" ref="memberDao"/>
</bean>

2.答案:

  1. 先创建 id=memberDao
  2. 再创建 id=memberService
  3. 调用 memberService.setMemberDao() 完成引用

3.测试: com/zzw/spring/test/SpringBeanTest.javatestBeanCreateOrder方法

java">public class SpringBeanTest {@Testpublic void testBeanCreateOrder() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");System.out.println("ok~");}
}

4.运行结果:

java">MemberDaoImpl 构造器...
MemberServiceImpl 构造器被执行
setMemberDao()...

1.先看下面的配置, 请问两个bean创建的顺序是什么? 并分析执行流程, src/beans.xml

xml"><bean class="com.zzw.spring.service.MemberServiceImpl" id="memberService"><property name="memberDao" ref="memberDao"/>
</bean><!--配置MemberDaoImpl对象-->
<bean class="com.zzw.spring.dao.MemberDaoImpl" id="memberDao"/>

2答案:

  1. 先创建 id=memberService
  2. 再创建 id=memberDao
  3. 调用 memberService.setMemberDao() 完成引用

3.测试: com/zzw/spring/test/SpringBeanTest.javatestBeanCreateOrder方法

java">public class SpringBeanTest {@Testpublic void testBeanCreateOrder() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");System.out.println("ok~");}
}

4.运行结果

java">MemberServiceImpl 构造器被执行
MemberDaoImpl 构造器...
setMemberDao()...

💖bean的单例和多实例

spring的ioc容器中, 默认情况下是按照单例创建的. 即配置一个bean对象后, ioc容器只会创建一个bean对象
如果我们希望ioc容器配置的某个bean对象, 是以多个实例形式创建的. 则可以通过配置 scope=“prototype” 来指定

1.新建com.zzw.spring.bean.Cat

java">public class Cat {private Integer id;private String name;public Cat() {//getter, setter方法
}

2.src/beans.xml增加如下配置

xml"><!--配置Cat对象
1.在默认情况下, scope属性是 scope="singleton"
2.在ioc容器中, 只会有一个这样的bean对象
3.当程序员执行getBean时, 返回的是同一个对象
4.如果我们希望每次返回一个新的bean对象, 则可以这样配置 scope="prototype"
5.如果bean的配置是 scope="singleton" lazy-init="true" 这时, ioc容器就不会提前创建该对象, 而是当执行getBean方法的时候, 才会创建对象
-->
<bean class="com.zzw.spring.bean.Cat" id="cat" scope="prototype" lazy-init="true"><property name="id" value="100"/><property name="name" value="花喵"/>
</bean>

3.测试: com/zzw/spring/test/SpringBeanTest.java增加testBeanScope方法

java">//测试Scope
@Test
public void testBeanScope() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");Cat cat1 = ioc.getBean("cat", Cat.class);Cat cat2 = ioc.getBean("cat", Cat.class);Cat cat3 = ioc.getBean("cat", Cat.class);System.out.println("cat1=" + cat1);System.out.println("cat2=" + cat2);System.out.println("cat3=" + cat3);
}

使用细节
1)bean默认是单例singleton; 在启动容器时, bean默认就会创建, 并放入到singletonObjects
2) 当<bean scope="prototype">设置为多实例机制后, 该bean是在getBean()时被创建
3) 如果是单例singleton, 同时希望在getBean时才创建, 可以指定懒加载 lazy-init="true"(注意默认是false)
4) 通常情况下, lazy-init 就使用默认值false. 在开发看来, 空间换时间是值得的, 除非有特殊要求
5) 如果scope="prototype", 这时你的lazy-init 属性的值不管是true还是false, 都是在getBean的时候才创建这个对象

💖bean的生命周期

bean对象创建是由JVM完成的, 然后执行如下方法

  1. 执行构造器
  2. 执行set相关方法
  3. 调用bean的初始化方法(需要配置)
  4. 使用bean
  5. 当容器关闭的时候, 调用bean的销毁方法(需要配置)

●代码实现
1.新建com.zzw.spring.bean.House

java">public class House {private String name;public House() {System.out.println("House构造器 被执行...");}public void setName(String name) {System.out.println("House setName()=" + name);this.name = name;}//解读//1.这个方法是由程序员来编写的//2.根据自己的业务逻辑来写.//3.名字也不是固定的public void init() {System.out.println("House init()....");}//解读//1.这个方法是由程序员来编写的//2.根据自己的业务逻辑来写.//3.名字也不是固定的public void destroy() {System.out.println("House destroy()...");}@Overridepublic String toString() {return "House{" +"name='" + name + '\'' +'}';}
}

2.配置src/beans.xml

xml"><!--配置House对象, 演示整个bean的生命周期
解读
1.init-method="init" 指定bean的初始化方法, 在setter方法后执行
2.init方法执行的时机, 由spring容器控制
3.destroy-method="destroy" 指定bean的销毁方法, 在容器关闭的时候执行
4.destroy方法执行的时机, 由spring容器控制
-->
<bean class="com.zzw.spring.bean.House" id="house"init-method="init" destroy-method="destroy"><property name="name" value="上海豪宅"/>
</bean>

3.测试bean的生命周期com.zzw.spring.test.SpringBeanTest

java">public class SpringBeanTest {@Testpublic void testBeanLife() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");House house = ioc.getBean("house", House.class);System.out.println("house=" + house);//关闭容器//1.ioc的编译类型 ApplicationContext, 运行类型 ClassPathXmlApplicationContext//2.因为ClassPathXmlApplicationContext 实现了 ConfigurableApplicationContext//3.ClassPathXmlApplicationContext 是有close()的//4.将ioc 转成ClassPathXmlApplicationContext, 再调用close()//ioc.close()//5.关闭ioc容器((ClassPathXmlApplicationContext) ioc).close();}
}

4.输出

java">House构造器 被执行...
House setName()=上海豪宅
House init()....
setMemberDao()...
house=com.zzw.spring.bean.House@327bcebd
House destroy()...

使用细节
1.初始化-init方法和destroy方法, 由程序员来指定
2.销毁方法就是当关闭容器时, 才会被调用


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

相关文章

洞察解读:“李彦宏:不只迷恋模型,更应追求应用”

目录 洞察解读&#xff1a;“李彦宏:不只迷恋模型&#xff0c;更应追求应用” 模型与应用的区别与联系 个性化应用的重要性与挑战 从技术到应用的转化 展望未来 结语 洞察解读&#xff1a;“李彦宏:不只迷恋模型&#xff0c;更应追求应用” 在当前人工智能技术飞速发展的…

Qt 统计图编程

学习目标&#xff1a;Qt 折线图&#xff0c;柱形图和扇形统计图编程 学习基础 Qt QChart 曲线图表操作-CSDN博客 学习内容 Qt中绘制三种常见的图表非常方便, 主要步骤如下: 1. 折线图: - 使用QLineSeries定义折线数据,添加多个坐标点 - 使用QValueAxis创建X轴和Y轴 - 将…

ShardingSphere的项目应用

1. 事情的起因 最近,随着业务的发展,我们的项目面临着日益增长的数据挑战。系统使用的数据库是mysql,每天的增量差不多在百万左右,由于没有进行分库分表,以前设置的单表保存已经越发不能满足需求,所以想维持表的性能,甲方考虑对这些大数据量的表进行分表操作,同时也采…

【香橙派AiPro】基于VGG16的火灾检测模型预测

目录 引言开发板介绍开发板使用准备工作工具文档 拨码开关镜像烧录连接开发板下载MobaXterm网线-SSH连接开发板设置WIFI连接WIFI-SSH连接开发板确定开发板IP方法 Vnc可视化WindowsiPad 开发工具安装 散热风扇基于VGG16的火灾检测模型预测数据集准备目录结构代码操作 安装宝塔最…

自动驾驶的规划控制简介

自动驾驶的规划控制是自动驾驶系统中的核心组成部分&#xff0c;它负责生成安全、合理且高效的行驶轨迹&#xff0c;并控制车辆按照这个轨迹行驶。规划控制分为几个层次&#xff0c;通常包括行为决策&#xff08;Behavior Planning&#xff09;、轨迹规划&#xff08;Trajector…

docker build 建立镜像,多出很多 none 的中间层镜像

虚悬镜像 仓库名、标签均为的镜像被称为虚悬镜像&#xff0c;一般来说&#xff0c;虚悬镜像已经失去了存在的价值&#xff0c;是可以随意删除的。 出现虚悬镜像的原因一般是在docker pull **:latest 时产生。当新版本发布后重新pull&#xff0c;旧的镜像名会被新镜像所占用&a…

车载视频监控管理方案:无人驾驶出租车安全出行的保障

近日&#xff0c;无人驾驶出租车“萝卜快跑”在武汉开放载人测试成为热门话题。随着科技的飞速发展&#xff0c;无人驾驶技术已逐渐从概念走向现实&#xff0c;特别是在出租车行业中&#xff0c;无人驾驶出租车的推出将为公众提供更为安全、便捷、高效的出行服务。 视频监控技…

【linux深入剖析】管道的四种情况以及五种特性

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1. 管道的四种情况2. 管道…

更新商品前端接口编写

文章目录 新增页面书写写表单价格符号的显示然后状态的书写后端枚举书写时间书写使用组件 新增页面书写 书写直接复制页面 写表单的绑定信息 然后绑定表单 表单绑定还有表单数据的绑定 标签中ref的作用就是将 该组件注册到vue对象的ref属性中 那么在vue运行的时候,会加载所…

【Redis】哨兵(sentinel)

文章目录 一、哨兵是什么&#xff1f;二、 哨兵sentinel文件参数三、 模仿主机redis宕机四、哨兵运行流程和选举原理SDOWN主观下线ODOWN客观下线 五、 使用建议 以下是本篇文章正文内容 一、哨兵是什么&#xff1f; 哨兵巡查监控后台master主机是否故障&#xff0c;如果故障了…

MacOS如何切换shell类型

切换 shell 类型 如果你想在不同的 shell 之间切换&#xff0c;以探索它们的不同之处&#xff0c;或者因为你知道自己需要其中的一个或另一个&#xff0c;可以使用如下命令&#xff1a; 切换到 bash chsh -s $(which bash)切换到 zsh chsh -s $(which zsh)$()语法的作用是运…

「Python」基于Gunicorn、Flask和Docker的高并发部署

目标预期 使用Gunicorn作为WSGI HTTP服务器,提供高效的Python应用服务。使用Flask作为轻量级Web应用框架,快速开发Web应用。利用Docker容器化技术,确保应用的可移植性和一致性。实现高并发处理,提高应用的响应速度和稳定性。过程 环境准备:安装Docker和Docker Compose。编…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【查询密钥是否存在(ArkTS)】

查询密钥是否存在(ArkTS) HUKS提供了接口供应用查询指定密钥是否存在。 开发步骤 指定密钥别名keyAlias&#xff0c;密钥别名最大长度为64字节。初始化密钥属性集。用于查询时指定密钥的属性TAG&#xff0c;比如查询的密钥范围(全量/单个)&#xff0c;当查询单个时&#xff…

公司想无偿裁员,同事赖着不走

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 这招好像也不错! 事情是这样的&#xff1a;某公司准备把成本高的员工都裁掉&#xff0c;主要包含研发部和程序员&#xff0c;总共18个人&#xff0c;准备裁掉10人&#xff0c;因为他们工资开的太高了&#xff0c;…

ArcGIS Pro、ChatGPT、Python、InVEST等多技术融合的水文、生态、气候变化等地学领域科研及项目综合能力提升

在当前科学技术飞速发展的背景下&#xff0c;综合科研能力的提升对于推动各个领域的创新和发展具有重要的意义。在当前竞争激烈的科研环境中&#xff0c;掌握先进的数据处理与分析技术、深入了解前沿的研究领域、有效利用智能工具进行科研工作&#xff0c;已成为科研人员脱颖而…

frp内网穿透xtcp安全点对点p2p部署记录打洞失败解决方法

环境 一、有公网IP、nas主机&#xff08;需要穿透里面的服务&#xff09;、安卓手机、frps-0.58.1、frpc-0.59.0(群晖NAS套件)、安卓版frpc-0.56.0 二、两端frpc必须要有一端nat网络类型不是非对称nat 开始 有公网的主机上配置frps.toml bindPort 7000nas主机端frpc.toml配…

定制化服务发现:Eureka中服务实例偏好的高级配置

定制化服务发现&#xff1a;Eureka中服务实例偏好的高级配置 在微服务架构中&#xff0c;服务实例的智能管理和优化是保证系统高效运行的关键。Eureka作为Netflix开源的服务注册与发现框架&#xff0c;提供了丰富的配置选项来满足不同场景下的需求。服务实例偏好配置允许开发者…

解决fidder小黑怪倒出JMeter文件缺失域名、请求头

解决fidder小黑怪倒出JMeter文件缺失域名、请求头 1、目录结构&#xff1a; 2、代码 coding:utf-8 Software:PyCharm Time:2024/7/10 14:02 Author:Dr.zxyimport zipfile import os import xml.etree.ElementTree as ET import re#定义信息头 headers_to_extract [Host, Conn…

Spring-Aop源码解析

本文主要讲解spring实现aop的相关源码学习教程&#xff0c;以aop.xml配置文件的方式为例&#xff0c;讲解如何将配置文件的标签解析成bean定义信息&#xff0c;存放到beanfactory中。以及advisor的bean定义信息以及实例化的过程&#xff1b;对哪些类进行代理&#xff0c;以及判…

[数仓]十二、离线数仓(Atlas元数据管理)

第1章 Atlas入门 1.1 Atlas概述 Apache Atlas为组织提供开放式元数据管理和治理功能,用以构建其数据资产目录,对这些资产进行分类和管理,并为数据分析师和数据治理团队,提供围绕这些数据资产的协作功能。 Atlas的具体功能如下: 元数据分类 支持对元数据进行分类管理,例…