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

news2024/11/27 4:22:56

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 --->  Date
                   SimpleDateFormat sdf = new SimpleDateFormat();
                   sdf.parset(String) ---> Date
    param: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 --->  Date
                       SimpleDateFormat sdf = new SimpleDateFormat();
                       sdf.parset(String) ---> Date
        param: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 {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public 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.coloradmin.cn/o/858740.html

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

相关文章

RestTemplate 请求转发异常 ERR_CONTENT_DECODING_FAILED 200 (OK)

#1 问题描述 在基于Spring Boot的项目中实现了请求转发&#xff08;使用 RestTemplate 的 exchange 方法&#xff09;的功能&#xff0c;忽然在前端报net::ERR_CONTENT_DECODING_FAILED 200 (OK)的错误&#xff0c;后端及上游系统日志均显示请求已完成。 #2 原因探寻 上述错…

黑马机器学习day3

1.线性回归 1.1线性回归的原理 线性关系 非线性关系 1.2线性回归的损失和优化原理 目标&#xff1a;求模型参数&#xff0c;模型参数能够使预测准确 1损失函数 2优化方法 正规方程&#xff1a;直接求解W梯度下降&#xff1a;试错&#xff0c;改进 1.3线性回归API 1线性回…

http、https笔记

目录 HTTP 基本概念状态码&#xff1a;get和post的区别&#xff1a;http 常⻅字段&#xff1a;http的缺点&#xff1a; HTTP/1.1HTTP/3HTTPSHTTPS和HTTP区别对称加密和⾮对称加密⾮对称加密 HTTP 基本概念 状态码&#xff1a; 1xx 中间状态&#xff0c;比如post的continue 20…

端口输入的数据为什么要打拍?

一次作者在开发图像时候&#xff0c;对输入的图像没有打拍&#xff0c;输出给显示终端&#xff0c;时好时坏&#xff0c;或者图像颜色不正确&#xff0c;最终经过打拍解决了此问题。 //配置为16-Bit SDR ITU-R BT.656模式时pixel_data[23:16]为高阻。always (posedge pixel_cl…

「文本隐写」相关会议期刊投稿注意事项

前言&#xff1a;本篇博客总结「文本隐写」研究领域相关会议与期刊的投稿注意事项。 目录 一、会议ACL (The Annual Meeting of the Association for Computational Linguistics)IH&MMSec (The ACM Workshop on Information Hiding, Multimedia and Security)CCS (The ACM …

ABAP通过弹窗函数POPUP_GET_VALUES修改数据内容

我们通过调用内置函数POPUP_GET_VALUES来实现弹框数据某些对应的数据内容. 具体参数以及语法如下. CALL FUNCTION POPUP_GET_VALUESEXPORTING * NO_VALUE_CHECK popup_title 物料商品选择 * START_COLUMN 5 * START_ROW 5IMPORTINGreturn…

opencv基础55-获取轮廓的特征值及示例

轮廓自身的一些属性特征及轮廓所包围对象的特征对于描述图像具有重要意义。本节介绍几个轮廓自身的属性特征及轮廓所包围对象的特征。 宽高比 可以使用宽高比&#xff08;AspectRation&#xff09;来描述轮廓&#xff0c;例如矩形轮廓的宽高比为&#xff1a; 宽高比 宽度&am…

Linux系统介绍

一、Linux系统和Windows系统的区别&#xff1a; 1.Linux主要使用命令行来操作系统&#xff0c;Windows是使用图形化界面来操作系统。 在Linux系统中可以通过在桌面鼠标右击选择在终端中打开然后通过终端来操作&#xff0c;也可以使用快捷键ctrlaltt进入终端&#xff1b;可以直…

修改el-select和el-input样式;修改element-plus的下拉框el-select样式

修改el-select样式 .select_box{// 默认placeholder:deep .el-input__inner::placeholder {font-size: 14px;font-weight: 500;color: #3E534F;}// 默认框状态样式更改:deep .el-input__wrapper {height: 42px;background-color: rgba(0,0,0,0)!important;box-shadow: 0 0 0 …

CSGO搬砖会被红锁吗?不清楚这些的话steam搬砖大家千万别做。

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 在CSGO游戏中&#xff0c;许多玩家通过搬砖赚钱。小编整理了相关资料。让我们看看&#xff0…

单芯片3路CC管理的VR转接器解决方案

VR眼镜即VR头显&#xff0c;也称虚拟现实头戴式显示设备&#xff0c;随着元宇宙概念的传播&#xff0c;VR眼镜的热度一直只增不减&#xff0c;但是头戴设备的续航一直被人诟病&#xff0c;如果增大电池就会让头显变得笨重影响体验&#xff0c;所以目前最佳的解决方案还是使用VR…

微信开发之一键修改好友标签的技术实现

移除标签下的好友&#xff1a; 把需移除的好友所有标签查出来&#xff08;通讯录详情接口返回标签id&#xff0c;数据库需缓存&#xff09;&#xff0c;去掉想移出的标签id&#xff0c;labelIdList参数放进其他所有标签id。 增加标签新好友&#xff1a; 把需添加的好友所有标签…

STM32入门——ADC模数转换

ADC简介 ADC&#xff08;Analog-Digital Converter&#xff09;模拟-数字转换器ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁12位逐次逼近型ADC&#xff0c;1us转换时间输入电压范围&#xff1a;0~3.3V&#xff0c;…

数据结构---B树

目录标题 B-树的由来B-树的规则和原理B-树的插入分析B-树的插入实现准备工作find函数insert中序遍历 B-树的性能测试B-树的删除B树B树的元素插入B*树的介绍 B-树的由来 在前面的学习过程中&#xff0c;我们见过很多搜索结构比比如说顺序查找&#xff0c;二分查找&#xff0c;搜…

C++ 计算 拟合优度R^2

解决的问题&#xff1a; 拟合优度(Goodness of Fit)是指回归直线对观测值的拟合程度&#xff0c;度量拟合优度的统计量是可决系数(亦称确定系数) R?。R最大值为 1。R%的值越接近1&#xff0c;说明回归直线对观测值的拟合程度越好&#xff0c;反之&#xff0c;R%值越小&#x…

腾讯云香港服务器租用价格_CN2线路延迟速度测试

腾讯云香港服务器&#xff0c;目前中国香港地域轻量应用服务器可选配置2核2G20M、2核2G30M、2核4G30M&#xff0c;操作系统可选Windows和Linux&#xff0c;不只是香港云服务器&#xff0c;新加坡、硅谷、法兰克福和东京服务器均有活动&#xff0c;腾讯云服务器网分享腾讯云境外…

Java开发要学哪些知识点?建议收藏

随着信息技术的快速发展&#xff0c;Java语言技能成为了企业招聘市场上最受欢迎的技能之一。在这样的市场需求下&#xff0c;Java开发也成为了很多人想要掌握的基本技能之一。那么&#xff0c;我们在学习Java开发时&#xff0c;应当掌握哪些知识点呢?下面&#xff0c;小编将为…

微信小程序调用map数据 并在wxml中对数组进行截取的操作

wxs文件的位置如图 实现数组截取 只保留五张图片 <wxs module"filter" src"./slicefunc.wxs"></wxs> <view class"wrap"><view class"search-box" bindtap"toSearch"><view class"v1"…

Linux系统的Centos7扩容主分区

前言&#xff1a;在学习C#的过程中电脑里面的项目&#xff0c;镜像越来越多之前装系统的时候分配的空间太小导致Linux系统空间不足&#xff0c;应该怎么办呢&#xff0c;lets go 跟着我来将centOS 7扩容吧. 1.关闭虚拟机&#xff0c;在VMWare的”此虚拟机设置“中找到硬盘&…

14个前端开发者应该知道的实用网站

在本文中&#xff0c;我将分享一些非常有用的网站合集&#xff0c;这些网站可以在你的日常工作中极大地帮助你。这些网站已经成为我各种任务的首选资源&#xff0c;节省了我的时间&#xff0c;提高了工作效率 文档自动化 Documatic 是一款专为开发人员设计的非常高效的搜索引擎…