Spring5学习笔记— 工厂高级特性

Springgif.gif

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉
🍎个人主页:Leo的博客
💞当前专栏: Spring专栏
✨特色专栏: MySQL学习
🥭本文内容:Spring5学习笔记— 工厂高级特性
🖥️个人小站 :个人博客,欢迎大家访问
📚个人知识库: 知识库,欢迎大家访问

1. 对象的生命周期

1.1 什么是对象的生命周期

含义:一个对象创建、存活、消亡的一个完整过程。

1.2 为什么要学习对象的生命周期

Spring 负责对象的创建、存活、销毁,了解生命周期,有利于我们使用好Spring为我们创建的对象。

1.3 声明周期的三个阶段

1. 创建阶段

  • scope="singleton"

    此时会在创建Spring工厂时,创建对象。

    注意:如果同时设置了lazy-init="true",那么会在获取对象ctx.getBean("")时创建。

  • scope="prototype"

    Spring工厂会在获取对象时,创建对象,即调用ctx.getBean("")方法时创建。

注意:如果有属性需要注入(DI),会在创建完成时立即进行注入。

2. 初始化阶段

创建阶段完成后,Spring会调用对象的初始化方法,完成对应的初始化操作。

程序员提供初始化方法的途径:

  1. 实现InitializingBean接口:

    //实现这个方法,完成初始化操作
    public void afterProperitesSet(){}
    
    1. 对象中提供一个普通的方法同时配置Spring配置文件:
    public void myInit(){}
    

    细节分析:

    • 如果一个对象即实现InitializingBean,同时又提供的普通的初始化方法 ,顺序:

      1. InitializingBean
      2. 普通初始化方法
    • 注入一定发生在初始化操作的前面

    • 什么叫做初始化操作:资源的初始化:数据库、IO、网络 …

3. 销毁阶段

Spring销毁对象ctx.close();前,会调用对象的销毁方法,完成销毁操作

程序员定义销毁方法的途径:

  1. 实现DisposableBean

    public void destroy()throws Exception{}
    
  2. 定义一个普通的销毁方法同时配置Spring配置文件:

    public void myDestroy()throws Exception{}
    
    <bean id="" class="" init-method="" destroy-method="myDestroy"/>
    

细节分析:

  • 销毁方法的操作只适用于 scope="singleton"
  • 销毁操作主要指资源的释放操作,比如io.close(); connection.close();

2. 配置文件参数化

2.1 什么是配置文件参数化

把Spring配置文件中需要经常修改的字符串信息,转移到一个更小的配置文件中。

  1. Spring的配置文件中存在需要经常修改的字符串?
    存在 以数据库连接相关的参数 代表
  2. 经常变化字符串,在Spring的配置文件中,直接修改
    不利于项目维护(修改)
  3. 转移到一个小的配置文件(.properties)
    利于维护(修改)

配置文件参数化:利于Spring配置文件的维护(修改)

2.2 配置文件参数化的开发步骤:

1. 提供一个小的配置文件

# 名字:随便
# 放置位置:随便jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/test?useSSL=false
jdbc.username = root
jdbc.password = root

2. Spring的配置文件与小配置文件进行整合

<context:property-placeholder location="classpath:/db.properties"/>

3. 在Spring配置文件中通过${key}获取小配置文件中对应的值

image-20200928215903162

3. 自定义类型转换器

1. 什么是类型转换器

Spring 提供了一种 Converter(类型转换器)的类型转换工具。在 Spring MVC 中,它的作用是在控制器方法对请求进行处理前,先获取到请求发送过来的参数,并将其转换为控制器方法指定的数据类型,然后再将转换后的参数值传递给控制器方法的形参,这样后台的控制器方法就可以正确地获取请求中携带的参数了。

Spring MVC 框架默认提供了许多内置的类型转换器,主要包括以下几种类型。

1.1 标量转换器

名称作用
StringToBooleanConverterString 到 boolean 类型转换
ObjectToStringConverterObject 到 String 转换,调用 toString 方法转换
StringToNumberConverterFactoryString 到数字转换(例如 Integer、Long 等)
NumberToNumberConverterFactory数字子类型(基本类型)到数字类型(包装类型)转换
StringToCharacterConverterString 到 Character 转换,取字符串中的第一个字符
NumberToCharacterConverter数字子类型到 Character 转换
CharacterToNumberFactoryCharacter 到数字子类型转换
StringToEnumConverterFactoryString 到枚举类型转换,通过 Enum.valueOf 将字符串转换为需要的枚举类型
EnumToStringConverter枚举类型到 String 转换,返回枚举对象的 name 值
StringToLocaleConverterString 到 java.util.Locale 转换
PropertiesToStringConverterjava.util.Properties 到 String 转换,默认通过 ISO-8859-1 解码
StringToPropertiesConverterString 到 java.util.Properties 转换,默认使用 ISO-8859-1 编码

1.2 集合、数组相关转换器

名称作用
ArrayToCollectionConverter任意数组到任意集合(List、Set)转换
CollectionToArrayConverter任意集合到任意数组转换
ArrayToArrayConverter任意数组到任意数组转换
CollectionToCollectionConverter集合之间的类型转换
MapToMapConverterMap之间的类型转换
ArrayToStringConverter任意数组到 String 转换
StringToArrayConverter字符串到数组的转换,默认通过“,”分割,且去除字符串两边的空格(trim)
ArrayToObjectConverter任意数组到 Object 的转换,如果目标类型和源类型兼容,直接返回源对象;否则返回数组的第一个元素并进行类型转换
ObjectToArrayConverterObject 到单元素数组转换
CollectionToStringConverter任意集合(List、Set)到 String 转换
StringToCollectionConverterString 到集合(List、Set)转换,默认通过“,”分割,且去除字符串两边的空格(trim)
CollectionToObjectConverter任意集合到任意 Object 的转换,如果目标类型和源类型兼容,直接返回源对象;否则返回集合的第一个元素并进行类型转换
ObjectToCollectionConverterObject 到单元素集合的类型转换

Spring MVC 对于基本类型(例如 int、long、float、double、boolean 以及 char 等)已经做好了基本类型转换。因此,通常情况下 Spring MVC 提供的这些类型转换器可以满足开发人员大多数的类型转换需求的。

注意:在使用内置类型转换器时,请求参数输入值需要与接收参数类型相兼容,否则会报 400 错误。

2. 类型转换器的作用

Spring通过类型转换器把配置文件中字符串类型的数据,转换成对象中成员变量对应类型的数据,进而完成了注入。

image-20200418201732220

3. 为什么要自定义类型转换器?

原因:实际应用中需要转换某种特定的类型,且Spring内部没有提供这种类型转换器时,需要程序员自己定义。

4. 自定义类型转换器的开发步骤

4.1 实现 Converter<>接口

public class MyDateConverter implements Converter<String, Date> {/*convert方法作用:String --->  DateSimpleDateFormat sdf = new SimpleDateFormat();sdf.parset(String) ---> Dateparam:source 代表的是配置文件中 日期字符串 <value>2020-10-11</value>return : 当把转换好的Date作为convert方法的返回值后,Spring自动的为birthday属性进行注入(赋值)*/public Date convert(String source) {Date date = null;try {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");date = sdf.parse(source);} catch (ParseException e) {e.printStackTrace();}return date;}
}

4.2 在Spring的配置文件中进行配置

<!-- 创建自定义转换器对象 -->
<bean id="myDateConverter" class="com.yuziyan.converter.MyDateConverter"/><!-- 在Spring中注册自定义的转换器 -->
<!-- 目的:告知Spring框架,我们所创建的MyDateConverter是一个类型转换器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><property name="converters"><set><ref bean="myDateConverter"/></set></property>
</bean><!-- 上面两步完成之后就可以直接使用了 -->

5. 细节

5.1 体会依赖注入(DI)

MyDateConverter中的日期的格式,可以通过依赖注入的方式,由配置文件完成赋值。

public class MyDateConverter implements Converter<String, Date> {private String pattern;public String getPattern() { return pattern; }public void setPattern(String pattern) { this.pattern = pattern; }/*convert方法作用:String --->  DateSimpleDateFormat sdf = new SimpleDateFormat();sdf.parset(String) ---> Dateparam:source 代表的是配置文件中 日期字符串 <value>2020-10-11</value>return : 当把转换好的Date作为convert方法的返回值后,Spring自动的为birthday属性进行注入(赋值)*/public Date convert(String source) {Date date = null;try {SimpleDateFormat sdf = new SimpleDateFormat(pattern);date = sdf.parse(source);} catch (ParseException e) {e.printStackTrace();}return date;}
}
<!--创建自定义类型转换器对象-->
<bean id="myDateConverter" class="com.yuziyan.converter.MyDateConverter"><property name="pattern" value="yyyy-MM-dd"/>
</bean>
ConversionSeviceFactoryBean 定义id属性,值必须是 conversionService

5.2 Spring框架内置日期类型的转换器

日期格式:2020/05/01 (不支持 :2020-05-01)

6. 后置处理Bean

6.1 BeanPostProcessor的作用:

对Spring工厂所创建的对象,进行再加工。

注意:BeanPostProcessor是接口

1. BeanPostProcessor

都是在目标对象被实例化之后,并且属性也被设置之后调用的

  • postProcessBeforeInitialization
    • 在afterPropertiesSet或者自定义的初始化方法(使用@bean注解中的initMethod()属性或者使用xml配置)之前执行
  • postProcessAfterInitialization
    • 在afterPropertiesSet或者自定义的初始化方法之后执行(如果是从FactoryBean中获取的对象,则只有这个方法会起作用,,postProcessBeforeInitialization以及afterPropertiesSet或者自定义的初始化方法都不会有作用)

2. InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置

在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean()方法的Object bean = resolveBeforeInstantiation(beanName, mbdToUse);方法里面执行了这个后置处理器

  • postProcessBeforeInstantiation
    • 在目标对象实例化之前调用,方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(一般都是代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
  • postProcessAfterInstantiation
    • 方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。如果该方法返回false,会忽略属性值的设置;如果返回true,会按照正常流程设置属性值。
  • postProcessPropertyValues
    • 方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法不会被调用。可以在该方法内对属性值进行修改
  • postProcessBeforeInitialization&postProcessAfterInitialization
    • 父接口BeanPostProcessor的2个方法

3. SmartInstantiationAwareBeanPostProcessor

智能实例化Bean后置处理器(继承InstantiationAwareBeanPostProcessor)

  • determineCandidateConstructors
    • 检测Bean的构造器,可以检测出多个候选构造器(Java好像只会确定唯一的备选的构造器)
  • getEarlyBeanReference
    • 循环引用的后置处理器,这个东西比较复杂, 获得提前暴露的bean引用。主要用于解决循环引用的问题,只有单例对象才会调用此方法
  • predictBeanType
    • 预测bean的类型,在最后的类型转化时会用到

4. MergedBeanDefinitionPostProcessor

  • postProcessMergedBeanDefinition
    • 缓存bean的注入信息的后置处理器,仅仅是缓存或者干脆叫做查找更加合适,没有完成注入,注入是另外一个后置处理器的作用(不实现这个方法,也能直接调用postProcessPropertyValues完成属性值的注入)

5. DestructionAwareBeanPostProcessor

  • postProcessBeforeDestruction
    • 在bean实例被销毁之前被调用

6.2 后置处理Bean的运行原理分析

在这里插入图片描述

程序员实现BeanPostProcessor规定接口中的方法:

参数一:Spring工厂创建好的对象
参数二:对象名字
返回值:返回的对象会交给Spring框架
Object postProcessBeforeInitiallization(Object bean String beanName)
作用:Spring创建完对象,并进行注入后,会运行Before方法进行加工

Object postProcessAfterInitiallization(Object bean String beanName)
作用:Spring执行完对象的初始化操作后,会运行After方法进行加工

实战中:
很少处理Spring的初始化操作:没有必要区分Before After。只需要实现其中的一个After方法即可
注意:
postProcessBeforeInitiallization(){
return bean对象
}

6.3 BeanPostProcessor的开发步骤

1. 实现 BeanPostProcessor接口

public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {Categroy categroy = (Categroy) bean;categroy.setName("xiaowb");return categroy;}
}

2. Spring的配置文件中进行配置

<bean id="myBeanPostProcessor" class="xxx.MyBeanPostProcessor"/>

3. BeanPostProcessor细节

BeanPostProcessor会对Spring工厂中所有创建的对象进行加工。

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

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

相关文章

创建型模式-原型模式

文章目录 一、原型模式1. 概述2. 结构3. 实现4. 案例1.5 使用场景1.6 扩展&#xff08;深克隆&#xff09; 一、原型模式 1. 概述 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 2. 结构 原型模式包含如下角色&#xff1a; …

使用windows搭建WebDAV服务,并内网穿透公网访问【无公网IP】

文章目录 1. 安装IIS必要WebDav组件2. 客户端测试3. 使用cpolar内网穿透&#xff0c;将WebDav服务暴露在公网3.1 打开Web-UI管理界面3.2 创建隧道3.3 查看在线隧道列表3.4 浏览器访问测试 4. 安装Raidrive客户端4.1 连接WebDav服务器4.2 连接成功4.2 连接成功 1. Linux(centos8…

【Vue-Router】路由入门

路由&#xff08;Routing&#xff09;是指确定网站或应用程序中特定页面的方式。在Web开发中&#xff0c;路由用于根据URL的不同部分来确定应用程序中应该显示哪个内容。 构建前端项目 npm init vuelatest //或者 npm init vitelatest安装依赖和路由 npm install npm instal…

ATF BL1 UFS初始化简单分析

ATF BL1 UFS初始化分析 1 ATF的下载链接2 ATF BL1 UFS 初始化简易流程图3 ATF BL1 ufs初始化简单过程分析3.1 调用过程3.2 hikey960_ufs_init3.3 dw_ufs_init3.3 ufs_init 以海思hikey960为例来介绍&#xff0c;简单介绍在ATF BL1阶段的初始化处理。 1 ATF的下载链接 https:/…

蓝帽杯 取证2022

网站取证 网站取证_1 下载附件 并解压 得到了一个文件以及一个压缩包 解压压缩包 用火绒查病毒 发现后门 打开文件路径之后 发现了一句话木马 解出flag 网站取证_2 让找数据库链接的明文密码 打开www文件找找 查看数据库配置文件/application/database.php&#xff08;CodeI…

截止到目前全量主体总数有多少?

企业主体类型 企业主体类型有很多种&#xff0c;一般我们会分为公司&#xff08;有限责任&#xff09;、合伙企业、个人独资企业、个体经营户这些类别。 今天我们按照企业&#xff0c;个体&#xff0c;组织的分类方式来看各个主体的总数。 企业&#xff1a;统一社会信用代码…

ARTS 挑战打卡的第7天 --- Ubuntu中的WindTerm如何设置成中文,并且关闭shell中Tab键声音(Tips)

前言 &#xff08;1&#xff09;Windterm是一个非常优秀的终端神器。关于他的下载我就不多说了&#xff0c;网上很多。今天我就分享一个国内目前没有找到的这方面的资料——Ubuntu中的WindTerm如何设置成中文&#xff0c;并且关闭shell中Tab键声音。 将WindTerm设置成中文 &…

Unity zSpace 开发

文章目录 1.下载 zSpace 开发环境1.1 zCore Unity Package1.2 zView Unity Package 2. 导入工程3. 发布设置4.功能实现4.1 用触控笔来实现对模型的拖拽&#xff1a; 5. 后续更新 1.下载 zSpace 开发环境 官网地址 1.1 zCore Unity Package zSpace 开发核心必须 1.2 zView …

机器人CPP编程基础-05完结The End

非常不可思议……之前四篇博文竟然有超过100的阅读量…… 此文此部分终结&#xff0c;没有继续写下去的必要了。 插入一个分享&#xff1a; 编程基础不重要了&#xff0c;只要明确需求&#xff0c;借助AI工具就能完成一个项目。 当然也不是一次成功&#xff0c;工具使用也需要…

计算机视觉一 —— 介绍与环境安装

傲不可长 欲不可纵 乐不可极 志不可满 一、介绍 研究理论和应用 - 研究如何使机器“看”的科学 - 让计算机具有人类视觉的所有功能 - 让计算机从图像中&#xff0c;提取有用的信息&#xff0c;并解释 - 重构人眼&#xff1b;重构视觉皮层&#xff1b;重构大脑剩余部分 计…

利用ChatGPT绘制思维导图——以新能源汽车竞品分析报告为例

随着人们对环境保护的日益关注和传统燃油汽车的限制&#xff0c;全球范围内对新能源汽车的需求不断增长。新能源汽车市场的激烈竞争使得了解各个竞品的特点和优劣成为关键。然而&#xff0c;针对这一领域的详尽竞品分析却常常需要大量时间和精力。 在此背景下&#xff0c;人工智…

Qt+C++自定义控件仪表盘动画仿真

程序示例精选 QtC自定义控件仪表盘动画仿真 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<QtC自定义控件仪表盘动画仿真>>编写代码&#xff0c;代码整洁&#xff0c;规则&…

2023国赛数学建模D题思路分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…

PHP原生类

什么是php原生类 原生类就是php内置类&#xff0c;不用定义php自带的类&#xff0c;即不需要在当前脚本写出&#xff0c;但也可以实例化的类 我们可以通过脚本找一下php原生类 <?php $classes get_declared_classes(); foreach ($classes as $class) {$methods get_clas…

Docker的基本概念及镜像加速器的配置

1.Docker的概念 由于代码运行环境不同&#xff0c;代码运行会出现水土不服的情况。运用docker容器会把环境进行打包&#xff0c;避免水土不服。docker是一种容器技术&#xff0c;它解决软件跨环境迁移的问题。 2&#xff0c;安装Docker 3.Docker架构 4.Docker镜像加速器的配…

我们常说这个pycharm里有陷阱,第三方库导入失败,看这里!

最近有小伙伴遇到了明明安装了 python 第三方库&#xff0c;但是在 pycharm 当中却导入不成功的问题。 ​ 一直以来&#xff0c;也有不少初学 python 的小伙伴&#xff0c;一不小心就跳进了虚拟环境和系统环境的【陷阱】中。 本文就基于此问题&#xff0c;来说说在 pycharm 当…

Spring Cloud 面试突击2

Spring Cloud 面试突击2 高并发&#xff1a;是一种系统运行过程中遇到的短时间大量的请求操作 响应时间&#xff1a; 吞吐量&#xff1a; QPS&#xff1a;数据库为维度 TPS 并发用户数 并发的维度&#xff1a;很多的 并发是不是达到的当前系统的瓶颈 缓存 &#xff08…

计算机网络—IP

这里写目录标题 IP的基本认识网络层与数据链路层有什么关系IP地址基础知识IP 地址的分类什么是A、B、C类地址广播地址用来做什么什么是D、E类广播多播地址用于什么IP分类的优点IP分类的缺点 无分类地址CIDR如何划分网络号和主机号怎么进性子网划分 公有 IP 地址与私有 IP 地址公…

指针---进阶篇(二)

指针---进阶篇&#xff08;二&#xff09; 前言一、函数指针1.抛砖引玉2.如何判断函数指针&#xff1f;&#xff08;方法总结&#xff09; 二、函数指针数组1.什么是函数指针数组&#xff1f;2.讲解函数指针数组3.模拟计算器&#xff1a;讲解函数指针数组 三、指向函数指针数组…

Maven基础之仓库、命令、插件机制

文章目录 Maven 仓库中央仓库和本地仓库中央仓库本地仓库 Maven 命令generate 命令compile 命令clean 命令test 命令package 命令install 命令 Maven 插件机制官方插件&#xff1a;Compile 插件Tomcat 7 插件 Maven 仓库 中央仓库和本地仓库 [✎] 简单一点说 中央仓库是一个网…