Spring基础篇:注入

news/2024/5/8 22:58:29/文章来源:https://blog.csdn.net/Facial_Mask/article/details/128137356

第一章:注入

一:什么是注入

(Injection)注入就是通过Spring的工厂类和spring的配置文件,对spring所创建的对象进行赋值,为成员变量进行赋值

二:为什么注入

为什么需要Spring工厂创建对象的时候给对象进行赋值呢?
1:通过配置文件进行注入也可以实现解耦合的这样的作用,直接写死在代码当中会引发耦合效应
2:通过编码的方式为成员边量进行赋值会出现耦合,注入的方式会避免这样的耦合的作用

三:如何注入

    <bean id = "person" class = "com.pactera.spring.Person"><!--property标签是复制标签,name属性是对应bean类中的属性。--><property name = "id"><value>10</value></property><property name = "name"><value>xjr</value></property></bean>

1:提供GS方法

为成员变量提供setget方法,这是注入的第一步

2:Spring的配置文件

四:注入好处

解耦合

五:Spring注入的思想

1:Spring获取到配置文件路径之后,调用demo4j这个第三方组件来对xml配置文件进行解析,根据解析的内容创建对应的对象
2:对象创建之后,根据property标签中的配置的属性的值,根据对象的set和get方法进行赋值操作。
总结:Spring会通过底层属性对应的set方法进行赋值才完成对应的赋值操作,这种方式我们也称为set注入
在这里插入图片描述

1:Set注入详解

1:针对于不同类型的成员变量,在标签中进行注入的方式也不一样,不过都得嵌套到property标签当中
2:JDK内置类型:jdk自定义的数据类型,或者叫引用类型
3:用户自定义类型:用户自定义的类型

1):JDK内置类型

1、string+8中基本类型。<property name = "id"><value>10</value></property><property name = "name"><value>xjr</value></property>
2、数组<property name="emails"><!--这个是为了定义数组--><list><value>suns@pactera.com</value><value>cuilei@pactera.com</value><value>kaixin@pactera.com</value></list></property>3、set集合<set><!--在这里能用value标签是因为在Set<String>属于八中基本类型和String的范畴。--><value>138111111111</value><!--ref这个标签是给自定义类的注入进行使用的。--><ref bean=""/><!--set集合当中还可以套用set集合--><set></set></set>
4、list集合<property name="address"><list ><!--这是list集合的写法,list集合是有序的,list集合是可以重复的。--><value>zpark</value><value>shangdi</value><value>xierqi</value><set></set><ref></ref><list></list></list></property>
5、map集合赋值方式<property name="qqs"><!--这里是map的写法。--><map><entry><key><value>suns</value></key><value>43222222222222</value></entry><entry><key><value>xiexei</value></key><value>43222222222222</value></entry>
<!--                <entry>当key或者value是对象的时候<key><value>zhang</value></key><ref bean="">43222222222222</ref><key><ref bean="">zhang</ref></key><ref bean="">43222222222222</ref></entry>--></map></property>
6、properties类型的赋值      
更加复杂的jdk类型比如说:date类型,需要成蹊苑自定义类型转换器进行,这是在工厂的高级部分进行讲解。  

2):用户自定义类型

A:第一种方式

1:第一步还是为成员变量提供get和set方法
2:第二步在配置文件中进行注入

补充说明:
1:通过这样一种编译时耦合与接口+配置文件中定义注入类型的这样的形式,最大程度上降低了代码的耦合型
2:这种写法代码冗余,而且会重复创建某个对象。写一个bean标签就会创建一个对象,而且注入的这个对象不可能被复用只能在这个对象中被引用,被注入的对象多次创建就会浪费虚拟机内存的资源

    /** @Description:给自定义引用类型赋值。* @Author: DaShu* @Date: 2021/5/28 16:02* result:说明配置文件当中这样写可以实现自定义类型的注入。*///<bean id="userService" class = "com.pactera.spring.UserServiceImpl">//    <property name="userDao">//        <!--这个dao对象只使用一次,并且不会被其他对象使用。-->//        <bean class = "com.pactera.spring.UserDaoImpl"/>//    </property>//</bean>//<bean id="userService" class = "com.pactera.spring.UserServiceImpl">//    <property name="userDao">//        <ref bean="userDao"/>//    </property>//</bean>//<bean id="userDao" class="com.pactera.spring.UserDaoImpl"></bean>//<ref local = "">这个标签从spring4就已经废除了,这个只能引用本配置文件中的bean@Testpublic void test11() throws Exception {ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");UserService userService = (UserService)ctx.getBean("userService");Class clazz = userService.getClass();Field userDao = clazz.getDeclaredField("userDao");userDao.setAccessible(true);//Object o = userDao.get(userService);//System.out.println(o.getClass().getTypeName());//com.pactera.spring.UserDaoImplSystem.out.println(userDao.getGenericType());System.out.println(userDao.getName());System.out.println(userDao.get(userService).getClass().hashCode() == UserDaoImpl.class.hashCode());//true}
    <bean id="userService" class = "com.pactera.spring.UserServiceImpl"><property name="userDao"><!--这个dao对象只使用一次,并且不会被其他对象使用。--><bean class = "com.pactera.spring.UserDaoImpl"/></property></bean>

B:第二种方式

Ref 是引用的意思
在这里插入图片描述
在这里插入图片描述

3):Set注入简化写法

A:基于属性的简化

执行test方法的快捷键是 ctrl+shift+f10
这是jdk类型的注入的形式。
<property name = "name"><value = "suns">
</property> 
该类型的简化写法
<property name = "name" value = "suns"/>
用value属性代替value标签。
注意:通过value属性只能简化八中基本类型和String类型。用户自定义类型:
<property name = "userDao"><ref bean = "userDao">
</property> 
<property name= "userDao" ref = "userDao"/>
注意:这种方式只能替换ref属性的形式。

B:基于p空间简化属性

适用于jdk的类型的简化:在这里插入图片描述**补充说明:**1) alt+enter可以导入这个命名空间P的配置,在这个配置当中,有了这个命名空间之后,Property标签就没用了。在这里插入图片描述

4):构造注入

注入:通过Spring的配置文件,为成员变量赋值
Set注入:Spring通过Set方法,通过配置文件,为成员变量赋值
构造赋值:Spring通过构造方法,通过配置文件,为成员变量赋值

A:开发步骤

1:提供有参构造方法
2: 提供spring的配置文件进行配置

    <bean id = "customer" class="com.pactera.spring.constructor.Customer"><!--一个这样的标签对应一个这样的参数。并且顺序还是对应的。--><constructor-arg index="0"><value>suns</value></constructor-arg><constructor-arg index="1"><value>102</value></constructor-arg></bean>
    /** @Description:用于测试构造工厂* @Author: DaShu* @Date: 2021/5/31 11:21*/@Testpublic void test13(){ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");Customer customer = (Customer) ctx.getBean("customer");System.out.println(customer.toString());//Customer{name='suns', age=102}}

B:构造方法的重载

第一种方式:
1)、 参数的个数不同时通过constructor-arg标签的个数进行区分
2)、参数相同时,通过在这个标签中引入type标签就可以解决

5):注入的总结

Set注入 vs 构造注入,未来这两种我们到底是使用什么注入
1:未来实战:使用set注入会更多,构造注入会更多,有重载,更麻烦,
2:Spring底层他自己的一些对象的配置,也是使用大量的set的注入,构造注入用的比较少。

在这里插入图片描述

第二章:反转控制和依赖注入

一:什么叫做控制反转

控制:控制值得是对于对象创建、程序变量赋值的控制权,控制和注入的关系不是并列的关系,控制翻转依赖注入的,注入是控制翻转中的一个环节,例如:直接在代码中完成对于成员边量的赋值,这提高了代码的耦合,这样的控制权是在代码中的,提高了耦合性,将成员变量的赋值权交给Spring工厂和他的配置文件,这样就通过注入的方式,控制权是在Spring上边,解开了耦合性。

控制反转也就是说:对于对象的创建、对象的成员变量的赋值的权利翻转到spring的工厂和配置文件当中,可以起到解耦合的作用,控制反转的好处解耦合的作用。

底层实现:工厂设计模式,反射+配置文件

代码编写中最好的降低耦合性的方式:
反射+配置文件+耦合月接口,可以把代码的耦合性降低早最低。
在这里插入图片描述

二:什么是依赖注入

通过Spring的工厂和配置文件为对象的成员变量赋值,依赖:我需要你的时候,你就是我的依赖:比如说:Service层中的Dao层的对象,就可以说Service层依赖dao层。Dao层是Service层的依赖。我依赖谁,就可以把他作为成员变量通过,spring的配置文件,创建他的对象,给我注入。好处:解耦合,通过提供set,get方法,最终通过Spring的配置文件完成对象的创建和注入

第三章:Spring创建复杂对象

一:复杂对象概念

什么是复杂对象?什么是简单对象?
1:简单对象,直接通过new 构造方法创建的对象
2:复杂对象,不能通过直接new构造方法的创建的对象

补充说明:
1:这些复杂对象大多都是Spring集成的一些其他优秀的框架中的核心类的对象,不能直接new,我们也希望Spring能够创建这些类的对象,保证Spring工厂什么对象都可以创建
2:Spring容器就是Spring工厂

二:常见的复杂对象

链接对象和SqlSessionFactory对象。

三:FactoryBean

1:概述

这种方式的本质在一个实现了BeanFactory这样的接口的Bean中,书写创建该复杂对象的代码,这样通过Bean对应id获取到的Bean是复杂对象的Bean而不是这个Bean的对象,Spring非常重要的一种机制,Spring原生提供的帮我们创建复杂对象的方式。

2:开发步骤

1:实现FactoryBean接口,在该类的getBean()方法代码中创建该类对象
2:在Spring的核心配置文件中配置这个类
3:通过这个工厂对象中的getBean方法获取该复杂对象

在这里插入图片描述

3:FactoryBean的Method

getObject()获取该复杂对象,调用这个方法获取到复杂对象,然后在调用Spring工厂对象进行getBean的时候将这个复杂对象进行返回

获取该复杂对象的Class对象,此对象也是Spring工厂进行调用

isSingleTon()这个方法返回的事TRUE或者FALSE如果是TRUE的话,表示的事单例设计模式,每次getBean的时候,获取的都是这一个对象,不会多次创建,如果是FALSE的话,每次创建都会创建一个新的复杂对象,返回的也是新的复杂对象

补充说明:
1:他这个复杂对象的创建每个跟每个都不一样,所以,spring是给定了接口,将对象创建的核心代码让你来写

在这里插入图片描述

四:Spring配置文件中的配置

配置文件当中这样写理论上Spring为我们创建的ConnectionFactoryBean的对象,但是我们使用getBean方法进行获取时候,获取的不再是这个类的对象,而是我们希望获取的复杂的对象
在这里插入图片描述
在这里插入图片描述

五:FactoryBean开发细节

1)、如果这个类型是FactoryBean类型的实现,我们获取的是复杂对象,如果我们就想获取这个FactoryBean类型的对象怎么办?getBean的时候,在id前面加上一个&符号,类似于getBean(“&conn”)这样的话就获取的是FactoryBean类型的对象,isSingleTon()方法返回TRUE的时候,只会创建一个对象,返回FALSE的时候,每次获取spring都会创建一个对象。
2)、Connection对象能够公用?
不能公用,链接对象一个很大的作用在于控制事务,假设一个链接开启了事务,假设两个用户都获取到了conn这个对象,你使用这个对象提交了事务,就影响到了我,那就不行。SqlSessionFactory这个对象是线程安全的,重量级的,之创建一次,应该创建一次,应该设置成TRUE。
3、获取Connnection对象的时候的一些细节?在这里插入图片描述
4)、我们对于依赖注入的体会
通过依赖注入的思想,将写死的内容变成成员变量,然后交由Spring进行依赖注入。获得解耦合的好处。
把Connection依赖的四个字符串信息,进行了依赖注入,好处就是解耦合。

5)、为什么pring要规定一个factoryBean接口要我们实现,并且将创建复杂对象的代码写在getObject()方法当中(FactoryBean实现原理)?
接口回调:在java体系当中,接口+反射什么都能做,本质上是一个接口回调,在Spring的底层代码中,通过id值获取ConnectionFactoryBean类的对象,进而判断是不是 BeanFactory接口的实现类(InstanceOf),如果是的话,Spring按照接口约定,调用getObject方法获取Connection对象,返回Connection对象

在这里插入图片描述
6)、为什么说Spring创建的复杂对象都是懒加载的?
Spring对于复杂对象的创建是懒加载的,使用FactoryBean创建复杂对象,在spring容器进行创建的时候只会先创建实现了FactoryBean这个类的对象,当getBean的时候才会有Spring的接口回调,获取复杂对象并进行返回,所以这是懒加载的

6、Factorybean总结
spring当中创建复杂对象的一种方式,也是spring原生提供的,后续我们讲整合其他框架时会大量应用BeanFactory这个接口的形式

六:实例工厂

1:为什么使用实例工厂

避免Spring框架的侵入,使用Spring框架进行复杂框架开发的时候,如果使用beanFactory进行开发的,必须使用Spring提供的BeanFactory接口,这样日后离开Spring的话,那么久没有什么意义了

应用实例工厂创建对象,主要是为了整合遗留系统,遗留系统中一些复杂对象的创建已经写好了,而且提供的是class文件不是java文件,这种情况处理的话,就是使用BeanFactory已经没办法了

class ConnectionFactory{public Connection getConnection(){Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "root");return connection;}
}
    <bean id="connFactory" class="com.pactera.spring.factorybean.ConnectionFactroy"></bean><bean id = "conn" factory-bean="connFactory" factory-method="getConnection"/>

七:静态工厂

实例工厂需要先创建实例工厂的对象,静态工厂当中直接类名.方法名进行调用就可以了,二者都是为了避免Spring的侵入,为了整合遗留的资源,以上就是Spring创建复杂对象的三种方式

1:配置文件上有些区别

    <!--静态工厂不需要创建对象,直接类名调用就完事了,用的比较少。使用的时候通过getBean("conn")获取的就是这个复杂对象。--><bean id = "conn" class="com.pactera.spring.factorybean.StaticConnectionFactory" factory-method="getConnection"/>

2:Spring工厂创建对象的总结

>

第五章:控制Spring工厂创建对象的次数

一:控制简单对象的创建次数

    <!--控制这个类的创建的次数,这个参数默认是SingleTon--><bean id="account" class = "com.pactera.spring.scope.Account" scope="singleton"/>
    /** @Description:测试spring只创建一个对象。* @Author: DaShu* @Date: 2021/5/31 14:31*/@Testpublic void test18(){ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");Account account = (Account)ctx.getBean("account");Account account1 = (Account) ctx.getBean("account");System.out.println(account == account1);//当是singleton的时候,spring只会创建一次这个对象。//当是prototype的时候,获取一次创建一次。//spring当中不写这个属性的时候,默认就是singleton。}

二:如何控制复杂对象的创建次数

FactoryBean接口当中的isSingleTon()重写的时候,return true即可。

实例工厂和静态工厂,还是以scope属性的方式进行控制。

三:为什么控制创建对象的次数

有些对象是可以大家公用的,可以公用的这些对象就创建一次就可以了,有些对象是不能公用的,不能公用的就一人创建一次,这样做就是节省内存的空间,节省不必要的内存浪费

什么样的对象只创建一次就行了
SqlSessionFactory这个mybatis工厂对象是一个重量级的对象,重量级的对象只创建一次就好了,Dao,的对象,Service只创建一次被大家公用就可以了

什么样的对象每次都创建新的呢
1:connection对象,设计到事务.
2:sqlSession对象,封装了连接对象。
3:Session对象。 Struct2当中Controller当中的actrion
总结:线程安全,可以公用,才只创建一次

第六章:对象的生命周期

一:什么是对象的生命周期

对象的生命周期指的是一个对象创建到销毁的完整的过程。

二:研究对象生命周期的意义

User user = new User();我们通过new的方式在java虚拟机当中创建了一个对象,只要有引用指向这个对象,对象就会一直存在于jvm内存当中,当虚拟机内存满了,或者整个进程结束了,那么这个对象就消亡了。

对象交由Spring进行创建和管理之后,对象的创建、存活(保存)、销毁都交由Spring进行管理,我们需要了解其中的原理,并且合理的进行利用。

三:声明周期三阶段

对象交由Spring创建之后,生命周期的三个阶段

1:创建阶段

Spring工厂创建对象,当对象的创建是scope = singleton的时候,spring工厂创建的同时,对象也就被创建了,当对象的创建是scope = prototype的时候,spring会在获取对象的同时创建对象。获取对象就是getBean()方法执行的时候

如果scope是 singleton但是我们就想在getBean()的时候获取对象,实现一种懒加载的情况,那么我们应该怎么做?添加一个lazy-init= true属性

总结:singleton情况默认是在工厂对象创建的时候就创建了,如果这个singleton类型想要做到懒加载的话,bean标签当中添加一个属性就好了,单例默认都不是懒加载,多例默认都是懒加载,如果想改变这个规则,可以添加一个属性。**

2:初始化阶段

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

初始化方法是谁提供:是由程序员根据需求,提供初始化方法,完成初始化操作。

初始化方法调用:spring的工厂来调用初始化方法

初始化方法的定义:spring为我们提供了两种定义对象初始化方法的途径,第一种是类实现InitializingBean这个接口,在这个接口当中为我们定义了一个方法,afterPropertiesSet()方法。可以把我们对象的初始化代码写到这里边,当spring识别类实现了这个接口之后,就会调用这个方法(这个接口耦合了spring的接口,造成了一定的侵入)。第二种方式不需要我们实现任何接口,在对象中提供一个普通的方法,这个方法 public void myInit(){} 方法名可以任意取,spring识别这个方法通过配置文件来告诉他应该调用哪个。这两种方法可以同时使用,回调会最先执行,初始化方法第二执行

    <bean id = "product" class = "com.pactera.spring.life.Product" init-method ="myInit"/>
    /** @Description:测试--afterPropertiesSet方法执行了 spring的初始化方法* @Author: DaShu* @Date: 2021/5/31 14:31* result:*/@Testpublic void test20(){ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");System.out.println("-----------------------工厂对象已经加载完毕------------------------");Product product = (Product) ctx.getBean("product");//Product.Product//afterPropertiesSet方法执行了。//myInit方法执行了。}

如果一个对象上上述两种方式都采用了,那么会怎么样?
先执行实现接口执行回调的方法,在执行普通的初始化方法。

Spring创建完对象之后会进行DI注入和初始化那么spring是先进行注入还是先进行初始化呢
Spring创建对象之后会先进行注入,注入完成之后在进行初始化。也就是先为成员边变量赋值,在进行初始化,所以,初始化方法叫做afterpropertyset,初始化方法经常用作资源的加载或者资源的初始化。

        //Product.Product  --构造方法创建对象//Product.setName  --set方法进行注入//afterPropertiesSet方法执行了。--接口方法进行初始话//myInit方法执行了。--普通方法进行初始化。

什么叫做初始化操作?
对于数据的初始化: 数据库-- IO—网络。所谓的初始化操作大多是资源的初始化,大部分情况下都是为了系统资源的初始化,这些操作会耗费时间占用内存资源,所以我们一般在系统启动的时候进行操作。**

3: 销毁阶段

什么叫做销毁阶段?
Spring销毁对象前会调用spring的销毁方法完成销毁操作

Spring什么时候销毁他所创建的对象呢
Spring 销毁他创建的对象,是在工厂关闭的时候,在工厂关闭之前也就是调用close方法的时候,spring工厂会销毁他所创建的对象

销毁方法是谁定义的
销毁方法是程序员定义的,程序员是根据需求完成销毁操作

销毁方法谁来调用呢
Spring来调用,Spring工厂来完成调用

如何定义销毁方法
定义销毁方法也有两种方式,第一种方法是实现spring的DisposableBean接口,通过实现其中方法进行销毁
另外一种就是通过标签的方式指定方法的名称。自定义一个普通的销毁方法。所谓的销毁操作就是资源释放的操作

    /** @Description:测试--destroy()方法* @Author: DaShu* @Date: 2021/5/31 14:31* result:*/@Testpublic void test21(){ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");Product product = ctx.getBean("product", Product.class);((ClassPathXmlApplicationContext)ctx).close();//Product.Product//Product.setName//afterPropertiesSet方法执行了。//myInit方法执行了。//2021-06-02 15:11:03 DEBUG ClassPathXmlApplicationContext:987 - Closing org.springframework.context.support.ClassPathXmlApplicationContext@5e4c8041, started on Wed Jun 02 15:11:02 CST 2021//Product.destroy//Product.MyDestroy}
    <!----><bean id = "product" class = "com.pactera.spring.life.Product" init-method ="myInit" destroy-method="MyDestroy"><property name="name" value="shit"/></bean>

销毁细节分析
销毁细节操作只适用于scope为singleton的作用,对于另外一种没有任何作用

什么叫做销毁操作
所谓的销毁操作值得一些资源的释放,比方说
io流的关闭,链接的关闭。这种销毁操作用的很少。

在这里插入图片描述

第七章:配置文件参数化

一:配置文件参数化

所谓的配置文件参数化就是把spring当中常用的常修改的字符串配置到配置文件当中,spring当中的配置文件是不是有哪些经常修改的字符串,为啥要转移到一个小的配置文件当中,这个小的配置文件是什么配置文件?

Spring的配置文件当中存在那些经常修改的字符串吗?
比方说阿里巴巴提供的连接池的配置当中需要提供四个属性,这四个属性是获取链接的必不可少的东西。驱动信息,账户和密码都有可能要变,所以需要写在配置文件当中,存在:以数据库连接相关的参数为代表。
在这里插入图片描述

字符串充斥在spring的配置文件当中是不是一个好事
这些东西跟spring的主配置文件放在一块就很累。开发不仅仅考虑一个功能实现的问题还需要考虑一个维护难度的问题

更小的配置文件用什么
我们更小的配置文件用的是properties文件,不用xml文件了。

在这里插入图片描述
信息转移走之后的配置应该怎么写
${}的含义表示的是这块的内容是需要使用运算得出的,不是el表达式的意思。value这块的值需要通过运算来获得,是需要通过key所对应的key进行填充,配置文件参数化:利于spring配置文件的维护,便于修改。
在这里插入图片描述
在这里插入图片描述

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

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

必须是properteis类型的配置文件,使用这个这个配置文件,主要保证是properteis进行结尾就行,至于是什么开头,放在哪里spring并不介意

2:将小配置文件和Spring配置文件进行整:

<!--    spring配置文件和小配置文件的整合,spring会自动帮我们把context命名空间引入进来,这是spring专门为了整合小配置文件做的一个命名空间--><!--小配置文件放在resource文件下边,对于这个maven项目来讲,main下边有java,还有和他同级的resource文件夹,maven开发的过程中是这样分级的,但是当编译过后,resource里边的文件会放到和com平级的地方看着仿佛是在java里边,编译会把两个目录合二为一,resource下边的文件相当于在java目录的根下边,所以是和com是平级的就对了,在maven项目中target目录代表的事这些项目编译好的结果,class文件夹是存放编译好的文件,class文件夹下com和配置文件是平级的。我们把class这个文件夹叫做类路径也就是我们的classpath,classpath同时也是spring当中配置文件的一个关键字,这个关键字代表的就是类路径,就是对应的class路径这样我们就做好了spring配置文件和小配置文件的整合--><context:property-placeholder location="classpath:db.properties"/><bean id="conn" class = "com.pactera.spring.factorybean.ConnectionFactoryBean"><property name="driverClassName" value="${jdbc.DriverManager}"/><property name="url" value="${jdbc.url}"/><property name="userName" value="jdbc.username"/><property name="password" value="jdbc.password"/></bean>

在这里插入图片描述

第八章:自定义类型转换器

一:什么是类型转换器

在之前的注入的时候,我们都忽略了一个细节,那就是在配置文件当中所写的内容都是字符串类型。那么如何给Integer类型进行赋值呢?当然是可以的。Spring是如何实现类型转换呢?spring实现这个类型转换的原因spring当中的类型转换器起的功效,他这个字符串类型转换器的底层也就是个Integer.parInt(“1”);这就是类型转换器最为核心的工作,就是数据类型的转换。

在这里插入图片描述
在这里插入图片描述

二:自定义类型转换器

就是我们对Spring当中的类型转换器不满意了,这是对于spring的框架的一种扩展;

1:Spring内置转换器不好使的情况*

在这里插入图片描述

    /** @Target: 测试spring的内置转换器不好使的时候。* @Author: DaShu* @Date: 2021/6/8 21:35* @Result: 某些格式的Date类型使用spring内置转换器就不好使了,需要自定义。*/@Testpublic void test23(){ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext2.xml");Object person = ctx.getBean("person");System.out.println(person);// Failed to instantiate [java.util.Date]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException//Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'birthday';// nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type// 'java.util.Date' for property 'birthday': no matching editors or conversion strategy found}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><bean id="person" class = "com.pactera.spring.converter.Person"><property name="name" value = "suns"/><property name="birthday" value="2021-04-01"/></bean>
</beans>
package com.pactera.spring.converter;
import java.util.Date;
/*** @Auther: DaShu* @Date: 2021/6/8 21:33* @Description:*/
public class Person {private String name;private Date birthday;public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}
}

对于日期格式来讲,spring并没有提供日期的转换器,因为地区和地区之间的格式都不一样,所以spring就没办法提供了,需要自己写,自己定制。

2:如何自定义类型转换器

需要实现converer接口,重写convert方法
用于解决类似于日期类型转换不过去的这样的情况。
这个代码写好之后需要交由spring进行创建对象,才能让Spring进行使用

/*** @Auther: DaShu* @Date: 2021/6/8 21:51* @Description:*/
public class MyDateConvert implements Converter<String, Date> {/** @Target: String -> Date* @Author: DaShu* @Date: 2021/6/8 21:54* @Result:*/@Overridepublic Date convert(String source) {//这个参数Source,他就代表了的是配置文件中的日期字符串//一旦converter进行了转换之后,怎么交给属性进行赋值呢?spring帮我们做了,返回值//spring会自动使用进行赋值。本质上就是一个简单的接口回调的事Date date = null;try{SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");date = sdf.parse(source);return date;}catch (Exception e){e.printStackTrace();}return date;}
}

3:Spring配置文件中进行注册

在Spring配置文件中进行配置即可

在Spring配置文件当中进行配置,第一将这个对象交由Spring进行创建,第二:类型转换器的注册:主要的目的及时告知Spring框架,我们所创建这个类是一个类型转换器,告诉了Spring之后,Spring就会把他当做Spring转换器对待,这样的话Spring就会在做日期类型转换的时候调用这个类当中个的方法,这就是注册的目的,注册也是在Spring的配置文件当中完成的。

注意:Spring配置文件当中bean标签的配置顺序和Spring的执行的顺序是没有关联的。所以,我们只需要在一个合适的位置进行配置就可以了。

注册的本质在于将这个咱们定义的这个格式转换器赋值给某个对象的属性。就注册到这里边了,这样到需要使用对应类型的类转换器的时候,Spring就会自动进行调用了。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><bean id="person" class = "com.pactera.spring.converter.Person"><property name="name" value = "suns"/><property name="birthday" value="2021-04-01"/></bean><bean id="myDateConvert" class = "com.pactera.spring.converter.MyDateConvert"/><!--这个类的作用是用于注册类型转换器--><bean id = "conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><!--调用set方法为属性进行赋值,这是spring定义的类中的属性,这个属性是set类型,需要使用set类型记性赋值--><property name="converters"><set><ref bean = "myDateConvert"/></set></property></bean>
</beans>
    /** @Target: 测试spring的内置转换器不好使的时候。* @Author: DaShu* @Date: 2021/6/8 21:35* @Result: 某些格式的Date类型使用spring内置转换器就不好使了,需要自定义。*/@Testpublic void test23(){ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext2.xml");Object person = ctx.getBean("person");System.out.println(person);//自定义类型转换器注册之后:com.pactera.spring.converter.Person@e1de817 代码正常执行。}

在这里插入图片描述

  • 细节介绍

这个simpledateformat工具类应该依赖这个yyyy-MM-dd这个,这个可以配置到spring的配置文件当中进行注入。

/*** @Auther: DaShu* @Date: 2021/6/8 21:51* @Description:*/
public class MyDateConvert implements Converter<String, Date> {private String pattern;public String getPattern() {return pattern;}public void setPattern(String pattern) {this.pattern = pattern;}/** @Target: String -> Date* @Author: DaShu* @Date: 2021/6/8 21:54* @Result:*/@Overridepublic Date convert(String source) {//这个参数Source,他就代表了的是配置文件中的日期字符串//一旦converter进行了转换之后,怎么交给属性进行赋值呢?spring帮我们做了,返回值//spring会自动使用进行赋值。本质上就是一个简单的接口回调的事Date date = null;try{SimpleDateFormat sdf = new SimpleDateFormat(pattern);date = sdf.parse(source);return date;}catch (Exception e){e.printStackTrace();}return date;}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><bean id="person" class = "com.pactera.spring.converter.Person"><property name="name" value = "suns"/><property name="birthday" value="2021-04-01"/></bean><bean id="myDateConvert" class = "com.pactera.spring.converter.MyDateConvert"><property name="pattern" value = "yyyy-MM-dd"/></bean><!--这个类的作用是用于注册类型转换器--><bean id = "conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><!--调用set方法为属性进行赋值,这是spring定义的类中的属性,这个属性是set类型,需要使用set类型记性赋值--><property name="converters"><set><ref bean = "myDateConvert"/></set></property></bean>
</beans>

配置文件当中定义注入了:
1:id属性我们唯一就行随便叫什么都行,但是需要大家注意的是:如果是ConversionServiceFactoryBean的话,他的id只能是conversionService大小写都得一样,如果他的id变了,就相当于没有注册进去,命名一定要慎重。
2:日期这种类型的话,Spring已经帮我们集成好了,默认的这种方式是2020/04/05这种形式,而我们自己写的这种形式的话,换了我们这种形式的话,Spring的默认的就不行用了。

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

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

相关文章

荟味齐鲁鲁菜网站/美食网站/菜谱网站

摘要 菜谱信息是餐厅必不可少的一个部分。在餐厅发展的整个过程中&#xff0c;菜谱信息管理担负着最重要的角色。为满足如今日益复杂的管理需求&#xff0c;各类管理系统程序也在不断改进。本课题所设计的荟味齐鲁鲁菜网站&#xff0c;使用SSM框架&#xff0c;Mysql数据库&…

智能聊天机器人如何帮助独立站运营提高工作效率?

关键词&#xff1a;智能聊天机器人、独立站运营 独立站运营变得越来越受欢迎&#xff0c;独立站可以用来建立在线商店并推动您的电子商务业务取得成功。它具有大量以业务为中心的功能&#xff0c;也许这就是为什么许多公司相信它会发展其在线业务的轨迹。 添加聊天机器人可以进…

基于51单片机电子微波炉控制系统(源程序+仿真+原理图+全套资料)

资料编号&#xff1a;203 功能介绍&#xff1a; 该电子微波炉采用51单片机制作&#xff0c;有基本的加热、冷却、启动、停止等功能&#xff0c;并通过MCU 控制其加热、冷却时间&#xff0c;LED 数码管显示时间。程序采用C语言编写&#xff0c;仿真使用Proteus&#xff0c;程序…

mysql与磁盘的关系

1.如今一直在说mysql存储方式和磁盘的关系&#xff0c;但是现在都是硬盘存储啊 磁盘分为硬盘和软盘 硬盘结构&#xff08;机械硬盘和固态硬盘&#xff09;详解 硬盘的大小是使用"磁头数 x 柱面数 x 扇区数 x 每个扇区的大小 如下&#xff1a; 每个扇区的大小是固定的…

Allegro添加渐近线操作指导

Allegro添加渐近线操作指导 Allegro支持添加渐近线,让线宽变化的地方进行圆环的过渡,对于射频信号优化有很大帮助,类似下图 具体操作如下 首先设置参数,route-Gloss-Parameters 点击Fillet and Taper Trace前面的方框 勾选Allowed DRC, Unused Nets 勾选Tapered Trac…

【毕业设计】大数据心血管疾病数据分析(医学大数据分析)

文章目录0 前言1 课题背景2 数据处理3 数据可视化4 最后0 前言 &#x1f525; Hi&#xff0c;大家好&#xff0c;这里是丹成学长的毕设系列文章&#xff01; &#x1f525; 对毕设有任何疑问都可以问学长哦! 这两年开始&#xff0c;各个学校对毕设的要求越来越高&#xff0c…

【Redis】缓存击穿的产生情况解决方案

1. 缓存击穿产生 也叫做 热点 Key 问题&#xff0c;高并发访问并且缓存重建业务较复杂的 key 突然失效了&#xff0c;无数的请求想要重建缓存&#xff0c;大量的访问会在瞬间给数据库带来巨大冲击。 2. 解决方案 2.1 方案一&#xff1a;互斥锁 查询缓存不存在时&#xff0c;…

天宇优配|上架秒光 “3时代”的大额存单受宠

“最近理财产品动摇比较大&#xff0c;准备处理一笔大额存单&#xff0c;但查询发现&#xff0c;某国有行暂时没有可购买的大额存单产品。”11月29日&#xff0c;成都市民王女士向金融出资报记者表示。 记者发现&#xff0c;虽然通过数次下调&#xff0c;中长期大额存单利率已步…

k8s网络插件之Calico

Calico简介 Calico官方文档&#xff1a;https://projectcalico.docs.tigera.io/getting-started/kubernetes/quickstart Calico是一套开源的网络和网络安全解决方案&#xff0c;用于容器、虚拟机、宿主机之前的网络连接&#xff0c;它是一个纯三层的虚拟化网络解决方案&#…

MYSQL中AS(取别名)

文章目录0 写在前面1 格式2 举例2.1 设置表别名2.2 设置字段别名3 写在末尾0 写在前面 在做业务&#xff0c;在mybatis中手写sql中再多表查询去映射实体时&#xff0c;总会用到AS这个关键字。 或者我们在数据库大量字段测试数据时&#xff0c;很多字段都有相同的前缀&#xff…

神仙级编程神器,吹爆

Visual Studio 编程领域公认的“最强IDE”&#xff0c;Visual Studio是目前最流行的Windows平台应用程序的集成开发环境&#xff0c;提供了高级开发工具、调试功能、数据库功能和创新功能&#xff0c;帮助在各种平台上快速创建当前最先进的应用程序&#xff0c;开发新的程序。 …

借助cubeMX实现STM32MP157A(-M4核)UART、按键中断、环境检测开关实验

main.c 可以添加一句打印提示 int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init(…

【内网安全】——Linux信息收集

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门 创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座…

行业应用之无限可能,就在亚马逊云科技re:Invent

在2022亚马逊云科技re:Invent全球大会Adam Selipsky“如何借助云的力量&#xff0c;在未知领域抓住机遇并茁壮成长”的主题演讲中&#xff0c;除了阐述主要的产品升级以外&#xff0c;亚马逊云科技还致力于打造面向特定行业或者特定应用场景的解决方案&#xff0c;以帮助客户快…

【react-笔记】

目录简介基本使用虚拟dom的两种创建方法jsx语法规则模块与组件、模块化和组件化的理解模块组件模块化组件化函数式组件类式组件组件实例三大属性statepropsrefs事件处理包含表单的组件分类非受控组件受控组件高阶函数_函数的柯里化生命周期引出生命周期理解生命周期(旧)总结新的…

基于jsp+mysql+ssm协同办公系统-计算机毕业设计

项目介绍 本公司文档协同办公管理系统采用SSM&#xff08;SpringSpringMVCMyBatis&#xff09;框架开发,主要包括系统用户管理模块、用户信息模块、文件信息管理、个人事务管理、资料信息管理、登录模块、和退出模块等多个模块. 本系统主要包含了等系统用户管理、用户信息管理…

数据结构学习笔记(Ⅶ):查找

目录 1 查找 1.1 定义 1.2 查找操作 1.3 算法评价指标 2 查找算法 2.1 顺序查找 1.算法思想 2.实现 3.查找效率 4.算法优化 2.2 折半查找 1.算法思想 2.算法实现 3.查找判定树 4.折半查找效率 2.3 分块查找 1.算法思想 2.查找效率分析 3 B树 3.1 B树概念 3…

独立站SaaS系统站群模式怎么玩

做独立站的人都知道“站群”这个游戏&#xff0c;意思是通过建站工具一次性建好几百个或者几千个独立站。各个独立站卖的品类比较垂直&#xff0c;不会有太多SKU。销量好的站会留着精细化运营&#xff0c;没流量的就放弃。 使用脸书或谷歌和其他广告渠道来测试产品。每个产品…

手把手教你写Linux线程池

手把手教你写Linux线程池 如果需要线程池源码&#xff0c;关注Linux兵工厂&#xff0c;并由大量Linux资料赠送。 线程池 顾名思义&#xff0c;存储线程的池子。线程池是线程的一种使用模式。在平常业务开发中常规的逻辑是遇到任务然后创建线程去执行。但是线程的频繁创建就类…

Java Tomcat内存马——Listener内存马

目录 &#xff08;一&#xff09;前置知识 0x01 什么是Listener 0x02 Listener的简单案例 0x03 Listener流程分析 &#xff08;二&#xff09;注入分析 (三&#xff09;实现内存马 得到完整的内存马 (四&#xff09;漏洞复现 其他的payload: 总结 &#xff08;一&#…