Spring(下)

接上篇,从第八个问题讲起

八.Spring工厂创建复杂对象

1.什么是复杂对象

简单对象就是可以直接new出来的,也就是直接调用构造方法创建

所以复杂对象就是不能直接通过调用构造方法创建。就比如JDBC中的Connection

2.三种方法

(1).FactoryBean接口

首先准备一个类,实现上述接口,进行文件配置。里面有三个方法:

getObject方法是用于书写创建复杂对象的代码,并将复杂对象作为方法返回值返回

getObjectType方法是返回复杂对象的class对象

isSingleton方法:若该对象只需创建一次(就是说每次都是用同一个对象),就让这个方法返回true;若每次使用都要创建一个新的对象,就让它返回false。

示例:

我们拿数据库建立连接来举例。既然要使用数据库,我们就要先引入数据库的依赖。

首先来实现getObject方法

其次就是getObjectType方法:

最后就是isSingleton方法

进行文件配置:

获取连接对象:

如上,虽然在配置文件中指定的是FactoryBean接口的实现类,但是获取到的却是Connection对象!!!这就是为啥要实现factorybean接口,原理会在后面讲到

细节分析:
如果就想获得factoryBean对象

在getbean方法中的conn前面加一个&即可

isSingleton方法

如果返回true,没那么每次创建的对象都是同一个:

如果返回false,则不是同一个:

依赖注入

对于connectionFactoryBean来说,下面几个内容是很重要的,是它所依赖的

所以要对他们进行set注入:

首先设置成成员变量,然后提供set方法,再去配置文件

FactoryBean实现原理

首先根据getBean传入的conn字符串获取对应bean标签的相关信息,

其次使用instanceof判断是否是factorybean的实现类

如果是就去执行重写的getObject方法来获取到connection对象,最后返回对象

总结

FactoryBean是Spring种用于创建复杂对象的方式,也是Spring原生提供的

(2).实例工厂

优势

实例工厂能够避免Spring框架的侵入,避免使用Spring提供的FactoryBean。

实力工厂也可以整合遗留系统

示例

写一个ConnectionFactory类作为遗留系统,

然后再配置文件中进行如下配置:

用到了factory-bean属性和factory-method属性

这样就把遗留系统整合了

(3).静态工厂

将getConnection方法换成静态的

配置文件如上

九.控制对象创建的次数

1.简单对象

在bean标签上加一个scope标签,值为singleton则只能创建一个对象,值为prototype(译为原型)则每次都创建新的对象

scope的值默认为singleton

2.复杂对象

就是使用issingleton方法。如果没有重写这个方法,那就还是默认使用scope属性,并且默认为singleton

3.为啥要控制?

有些对象,比如userDao,就可以被共用,有些不可以

好处:节省不必要的内存浪费

十.对象的生命周期

共分为三个阶段

1.创建阶段

Spring工厂何时创建对象?

当scope为singleton时,就是在Spring工厂创建的同时(也就是new ClassPathXmlApplicationContext)进行对象的创建

当scope为prototype时,就是在获取对象时(getBean方法)进行创建

如何证明?我们在person的无参构造中加一个控制台输出

先指定scope为singleton,调试一下:

这次指定scope为prototype,调试一下:

如上,当执行完创建工厂的代码时,控制台没有creat person的字样,但再往下看:

当执行完getBean方法后,出现了person无参构造这个打印语句

注:若scope为singleton,但还是想在获得对象时进行对象创建

则在bean标签中加一个lazy-init属性并且指定为true

2.初始化阶段:

Spring工厂创建完对象后,会调用初始化方法。该初始化方法是程序员提供,Spring工厂进行调用。那么如何提供初始化方法?有两种方式

方式一:InitializationBean接口

创建一个product类,实现initialization接口,并且实现其中的方法afterPropertiesSet

其实看这个方法的名字就知道,该方法的执行时期就是在property标签的set注入执行完毕后进行

下面进行文件配置:

方式二.在对象中提供普通的初始化方法,不实现接口

文件配置:

结果:

细节分析

若一个对象既实现类InitializationBean接口,又写了自己的初始化方法

那么就是先执行接口的方法,再执行自己的方法

如果还有property标签进行注入

那么就先注入,再初始化

初始化操作的意义

一般用在资源初始化中:数据库,IO,网络等

3.销毁阶段

Spring工厂在销毁之前,会调用对象的销毁方法,完成销毁操作

Spring何时销毁对象?

在调用ctx.close方法之后进行

如何销毁?

程序员定义销毁方法,Spring调用

方式一:实现DisposiableBean接口的destroy方法

文件配置:

效果:

为什么调用不了close方法呢?因为编译阶段不知道ctx的具体类型,不知道是classpathxmlapplicationcontext调用的还是webxmlapplicationcontext调用的,所以要向下转型,进行强制类型转换:

方式二:不实现接口,提供普通的销毁方法

细节分析

注意:销毁操作只适用于scope=singleton

销毁操作主要是指资源释放的操作,比如io,connection等

十一.配置文件参数化

指的是把Spring配置文件中,需要经常进行修改的字符串信息,转移到一个更小的配置文件中。规定此配置文件就是.properties文件。

有需要经常修改的字符串吗?当然有,就比如之前讲到的connection的创建,进行依赖注入,那些信息就很可能要修改(比如要换一个数据库)

1.好处

将进场需要修改的字符串转移到小的配置文件中,更利于修改,在改动的同时不会影响Spring配置文件中的其他内容

2.开发步骤

还是使用connection举例

提供小配置文件

我们创建一个db.properties文件

也是key value模式,key可以随便起名

将Spring配置文件与小配置文件进行整合

context:property-placeholder标签,表示读取小配置文件,location属性定义了小配置文件的路径。其中,classpath是Spring配置文件中特有的关键字,代表了target目录下的classes目录。

maven项目:开发时,java和resource目录是两个目录,但是编译后就合二为一了。如何证明?target目录存放的就是编译后的文件,打开就可以看到classes目录下面就有之前java和resource目录下的所有.class文件

将字符串填充到配置文件中:

"${key}"key就是小配置文件中的key

十二.自定义类型转换器

1.什么是类型转换器

在person类中,id是int类型,而Spring配置文件也是文件,它里面的内容就应该是字符串,那它怎么就把字符串赋值给了int类型呢?这是因为Spring中内置了类型转换器Converter,并且借助接口实现(为啥是接口?因为字符串要转换成不同的类型)

但是像date类型,每个地区的人的习惯性写法不同,所以Spring就可能无法将日期字符串转化成标准的Date格式(后面会讲为什么是可能)。那该怎么办?这就要我们程序员自定义类型转换器了

2.自定义类型转换器

创建一个Converter包,Person类

再写一个converter接口的实现类

Converter是一个泛型接口,见括号中的第一个表示原始类型,第二个表示要转换成什么类型

接下来我们就要去实现convert方法,这个方法的参数就是Spring配置文件中要被转换的那个字符串

最后在Spring配置文件中配置

首先要将自己写的类型转换器创建出来,然后要在Spring中进行注册。如何注册?

Spring中提供了一个类ConverterFactoryBean,它里面存放的就是各种类型转换器,是以Set集合存储的

所以要想使用自己的类型转换器,就要将自己写的类型转换器存放到set集合中,就如上所示。这样,就能将字符串转化成Date类型啦

3.细节分析

yyyy-MM-dd

它是MydateConverter的依赖项,所以可以对它进行依赖注入,也就是将它作为成员变量进行配置,后需要想修改格式,只需要修改Spring文件即可,就不用重新编译部署,就可以解耦合

为ConverterFactoryBean设标签

要注意id值必须为converterService,否则注册类型转换器不成功

Spring其实内置了日期的类型转换器

但它要求日期格式必须为:四位/二位/二位,否则无法自动转换

十三.后置处理bean

1.Spring创建对象的流程

1.反射调用构造方法

2.DI(注入)

3.InitializingBean的afterPropertySet方法对对象进行初始化

4.init-method="myInit",自定义的初始化方法

学到这里,我们就要再加一个BeanPostProcessor接口,他就是对Spring工厂所创建的对象进行再加工(就像苹果从果园中生长出来后没有直接到顾客手里,而是进行了再加工,提高了品质)

该接口中有两个方法

一个是Before,表示在调用InitializingBean接口的方法之前进行,一个是After,表示在调用了自定义的初始化方法之后进行

2.开发步骤

我们准备一个beanPost包和Category类

进行文件配置:

然后创建一个MyBeanPostProcessor类,实现BeanPostProcessor接口

我们没有实现这两个方法,但是没有报错,这是因为这两个方法是default,表示接口的默认实现

我们的目的是将name属性从小红改为小明。那该如何实现这两个方法呢?如下:

在实际开发中,很少会进行初始化操作,所以上面这两个方法实现一个即可,一般是实现after方法,另一个就返回bean。

最后进行文件配置

效果:

运行后竟然报错了!这是我们之前写的类型转换器不能转换成Category类。这是啥错误?

仔细看这个配置文件,里面有好多个bean标签,最后一个bean标签就是在创建beanPostProcessor的实现类,事实上,同一个配置文件中的对象都要调用BeanPostProcessor接口的方法,即下面我们重写的这个方法:

注意这个bean,这个bean可不是单单是Category对象,而将会是同一个配置文件中的所有对象,所以在话蓝线的这一句就会出现类型转换异常。那么该如何解决此问题?如下:

首先用instanceof判断一下是否是Category类,如果是才能进行下面的修改操作,不是就直接返回,返回的时候也是直接返回bean对象即可

所以一定要注意:​​​​​​​beanPostProcessor会对Spring文件中的所有对象进行加工,所以一定要进行类型匹配的判断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/827112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【华为 ICT HCIA eNSP 习题汇总】——题目集18

1、SSH默认工作使用的TCP端口号是()。 A、20 B、21 C、22 D、23 考点:①传输层 ②应用层 解析:(C) SSH为建立在应用层和传输层上的安全协议,是对TCP/IP协议的传输层以上的SSH会话流程进行加密的…

必应搜索广告与谷歌搜索广告对比那个更好?

搜索引擎广告作为企业获取潜在客户的重要渠道之一,其效果直接关系到营销策略的成功与否。两大搜索引擎巨头——谷歌(Google)和必应(Bing)各自提供了广告平台,即谷歌广告(Google Ads)…

【Web】2022DASCTF X SU 三月春季挑战赛 题解(全)

目录 ezpop calc upgdstore ezpop 瞪眼看链子 fin#__destruct -> what#__toString -> fin.run() -> crow#__invoke -> fin#__call -> mix.get_flag() exp <?php class crow {public $v1;public $v2;}class fin {public $f1; }class what {public $a; }…

力扣hot100(python解析)

文章目录 13. 合并区间14. 轮转数组 13. 合并区间 合并区间 数组 排序 思路&#xff1a; 代码&#xff1a; class Solution:def merge(self, intervals):result []if len(intervals) 0:return result # 区间集合为空直接返回intervals.sort() # 默认按照区间的左边界进…

z3求解器脚本(CTF-reverse必备)

CTF-reverse中有一类题目是通过约束方程求解变量的值&#xff0c;然后转化为对应的ASCII码&#xff0c;最终获得flag&#xff0c;约束方程以及要求解的未知数往往非常多&#xff0c;因此手算十分不现实&#xff0c;借助python中的z3模块可以很快完成求解&#xff01; 下面是某道…

开始Java之旅

1.Java语言 java是一门优秀的程序设计语言&#xff0c;并且是一种半编译型&#xff0c;半解释型语言。 Java 语言源于 1991 年 4 月&#xff0c;Sun 公司 James Gosling博士 领导的绿色计划(Green Project) 开始启动&#xff0c;此计划最初的目标是开发一种能够在各种消费性电…

【分治算法】Hanoi塔问题Python实现

文章目录 [toc]问题描述Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;Python基础 学习指南&#xff1a;Python学习指南 问题描述 设 a a a、 b b b、 c c c是三个塔座&#xff0c;开始时&#xff0c;在塔座 a a a上有一叠共 n n n个圆盘&#xff0c;这些圆盘…

最新免费 ChatGPT、GPTs、AI换脸(Suno-AI音乐生成大模型)

&#x1f525;博客主页&#xff1a;只恨天高 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ ChatGPT3.5、GPT4.0、GPTs、AI绘画相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容…

虚良SEO怎么有效的对百度蜘蛛权重优化?

人们交换链接通常首先要问的是你BR值是多少&#xff1f;国内搜索引擎来说以百度马首是瞻&#xff0c;无论seo还是竞价都看重的是百度&#xff0c;那么针对百度权重的优化就特别重要了。其实&#xff0c;百度权重是民间的一种说法&#xff0c;百度官方并没有认同这个数值&#x…

(回溯)记忆化搜索和dp

动态规划的核心就是 状态的定义和状态的转移 灵神 的 回溯改递归思路 首先很多动态规划问题都可以采用 回溯 的思想 回溯主要思想就是把 一个大问题分解成小问题 比如 采用子集类回溯问题中的核心思想-> 选或不选 或者 选哪个 记忆化搜索之后 我们可以发现 每个新节点依…

Oracle故障处理:ORA-00600错误处理思路

提前说明&#xff1a; 该故障&#xff0c;我只是旁观者。 但处理该故障的DBA工程师&#xff0c;思路很清晰&#xff0c;我非常受教&#xff01;在此也将经验分享。 目录 项目场景 问题分析 优化建议 项目场景 在某项目数据库运维群&#xff0c;有现场同事发了张报错截图如下…

代码学习记录49---单调栈

随想录日记part49 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.04.20 主要内容&#xff1a;今天开始要学习单调栈的相关知识了&#xff0c;今天的内容主要涉及&#xff1a;柱状图中最大的矩形 84.柱状图中最大的矩形 Topic184.柱状图中最大的矩形 题目&…

Scikit-Learn支持向量机分类

Scikit-Learn 支持向量机分类 1、支持向量机&#xff08;SVM&#xff09;1.1、SVM概述1.2、SVM原理1.3、SVM的损失函数1.4、支持向量机分类的优缺点 2、Scikit-Learn支持向量机分类2.1、Scikit-Learn支持向量机分类API2.2、支持向量机分类初体验&#xff08;手写数字识别&#…

四川易点慧电子商务抖音小店:安全正规,购物新选择

在当今互联网高速发展的时代&#xff0c;电子商务已经成为人们日常购物的重要组成部分。四川易点慧电子商务抖音小店作为新兴的电商平台&#xff0c;凭借其安全正规的经营理念和便捷高效的购物体验&#xff0c;正逐渐赢得消费者的信赖和喜爱。 一、平台背景实力雄厚 四川易点慧…

Windows11+Ubuntu20.04系统重装(升级为Ubuntu22.04)

事情起因是标题所对应的双系统中&#xff0c;Ubuntu老自动断电关机&#xff0c;一开始是跑大型程序才会关机&#xff0c;这两天愈演愈烈变成运行一个远程控制或者VSCode就会关机。一怒之下找了Dell在线客服&#xff0c;在对方引导下检测了硬件系统&#xff0c;发现没有明显故障…

STM32单片机C语言模块化编程实战:按键控制LED灯详解与示例

一、开发环境 硬件&#xff1a;正点原子探索者 V3 STM32F407 开发板 单片机&#xff1a;STM32F407ZGT6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F4 V1.27.1 之前介绍了很多关于点灯的方法&#xff0c;比如…

4.20 IO流

IO流结构 InputStream&#xff08;字节输入流&#xff09; public static void main(String[] args) {// byteInputStream();// byteInputStream1();// byteInputStream2();byteInputStream3();}// 使用字节流时对于中文汉字基本都会出现乱码问题&#xff0c;因此对中文乱码问…

mininet+odl安装

安装环境 ubuntu-18.04.2-desktop-amd64 Java version: 1.8.0_362 Apache Maven 3.6.0 opendaylight: distribution-karaf-0.6.0-Carbon(csdn中应该是已有资源&#xff0c;不让上传) opendaylight的官网下载链接一直打开失败&#xff0c;我使用的是别人的Carbon版本。 在安…

yml文件解析

.yml 后缀的文件可以有多个application.yml # 项目相关配置 用于 RuoYiConfig.java ruoyi:# 名称name: RuoYi# 版本version: 3.8.5# 版权年份copyrightYear: 2023# 实例演示开关demoEnabled: true# 文件路径 示例&#xff08; Windows配置D:/ruoyi/uploadPath&#xff0c;Lin…

C语言结构体,枚举,联合

系列文章目录 第一章 C语言基础知识 第二章 C语言控制语句 第三章 C语言函数详解 第四章 C语言数组详解 第五章 C语言操作符详解 第六章 C语言指针详解 第七章 C语言结构体详解 第八章 详解数据在内存中的存储 第九章 C语言指针进阶 文章目录 1. 结构体 1.1 声明结构…