- Bean的实例化方式
- 通过构造方法实例化
- 通过简单工厂模式实例化
- 通过factory-bean实例化(工厂方法模式实例化)
- 通过FactoryBean接口实例化
七、Bean的实例化方式
- Spring 为
Bean提供了多种实例化方式,包括如下 4 种方式:- 第一种:通过构造方法实例化。
- 第二种:通过简单工厂模式实例化。
- 第三种:通过
factory-bean实例化(工厂方法模式实例化)。 - 第四种:通过
FactoryBean接口实例化。
- Spring 中为
Bean对象的创建准备了多种方案,目的是为了能够更加灵活。
7.1 通过构造方法实例化
我们之前一直使用的就是这种方式。
默认情况下,会调用
Bean的无参数构造方法。在 Spring 配置文件中直接配置类的全路径,即在 Spring 配置文件中配置
bean,Spring 会自动调用该类的无参数构造方法来实例化Bean。1
2
3
4
5
6
7
8package com.f.spring6.bean;
/**
* @author fzy
* @date 2024/1/20 16:40
*/
public class SpringBean {
}1
2
3
4
5
6
7
8
9
10
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
Spring提供的实例化方式第一种:通过构造方法实例化
在Spring配置文件中直接配置类的全路径,Spring会自动调用该类的无参数构选方法米实例化Bean
-->
<bean id="springBean" class="com.f.spring6.bean.SpringBean"/>
</beans>1
2
3
4
5
6
public void testInstantiation1() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
SpringBean springBean = applicationContext.getBean("springBean", SpringBean.class);
System.out.println(springBean);
}
7.2 通过简单工厂模式实例化
1 | package com.f.spring6.bean; |
1 | package com.f.spring6.bean; |
1 |
|
1 |
|
7.3 通过factory-bean实例化(工厂方法模式实例化)
1 | package com.f.spring6.bean; |
1 | package com.f.spring6.bean; |
1 | package com.f.spring6.bean; |
1 | package com.f.spring6.bean; |
1 |
|
1 |
|
7.4 通过FactoryBean接口实例化
以上的第三种方式中,
factory-bean(生产bean的工厂bean)是我们自定义的,factory-method(生产bean的工厂方法)也是我们自己定义的。在 Spring 中,当我们编写的类直接实现
FactoryBean接口之后,用于创建bean的factory-bean就不需要我们指定了,工厂bean的factory-method也不需要我们指定了。factory-bean会自动指向实现FactoryBean接口的类,factory-method会自动指向该类中的getObject()方法。- 因为我们在配置文件中指定的用于创建
bean的类在实现FactoryBean接口之后,Spring 就知道这是一个工厂类,并且知道用于创建bean的工厂方法是哪个。
第四种方式实际上就是第三种方式的简化。
- 因为我们在配置文件中指定的用于创建
FactoryBean在 Spring 中是一个接口,被称为 “工厂Bean”。- “工厂Bean” 是一种特殊的
Bean,所有的 “工厂Bean” 都是用来协助 Spring 框架来创建其他Bean对象的。
- “工厂Bean” 是一种特殊的
1 | package com.f.spring6.bean; |
1 | package com.f.spring6.bean; |
1 |
|
1 |
|
- 相比于通过构造方法进行
bean的实例化(第一种方式),采用工厂方法进行bean的实例化(第二、三、四种方式),可以使我们在bean对象创建出来到将创建出来的对象交给 Spring 容器进行管理这一段时间内,对bean对象进行加工处理。
7.5 BeanFactory和FactoryBean的区别
BeanFactory
BeanFactory:Spring 容器的顶级父接口。- Spring IoC 容器的顶级对象,
BeanFactory被翻译为 “Bean工厂”,在 Spring 的 IoC 容器中,“Bean工厂” 负责创建Bean对象,即BeanFactory是一个创建bean对象的工厂。 BeanFactory是工厂。
FactoryBean
FactoryBean:它是一个Bean,是一个能够辅助Spring实例化其它Bean对象的一个Bean。- 在 Spring 中,
Bean可以分为两类:- 第一类:普通Bean。
- 第二类:工厂Bean,工厂 Bean 也是一种
Bean,只不过这种Bean比较特殊,它可以辅助 Spring 实例化其它Bean对象,即工厂 Bean 是一种用于创建Bean对象的Bean。 - 我们自己写的,用于实例化
Bean对象的工厂 Bean 就是FactoryBean。 - 工厂 Bean 是一种特殊的
Bean,是用于获取其他Bean的一种特殊Bean。FactoryBean是Bean。
7.6 FactoryBean实战练习 - 注入自定义Date
java.util.Date在 Spring 中被当做简单类型,简单类型在注入的时候可以直接使用value属性或value标签来完成。- 但是对于
Date类型来说,采用value属性或value标签赋值的时候,对日期字符串的格式要求非常严格,必须是这种格式的:Mon Oct 10 14:30:26 CST 2022。其他格式是不会被识别的。
- 但是对于
采用工厂方法模式可以让我们以非简单类型的方式,通过
FactoryBean接口实例化Date对象,同时还可以对Date对象进行加工,从而不需要严格按照日期字符串的格式要求,也能创建出日期对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package com.f.spring6.bean;
import java.util.Date;
/**
* @author fzy
* @date 2024/1/20 21:44
*/
public class Student {
private Date birth;
public void setBirth(Date birth) {
this.birth = birth;
}
public String toString() {
return "Student{" +
"birth=" + birth +
'}';
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package com.f.spring6.bean;
import org.springframework.beans.factory.FactoryBean;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author fzy
* @date 2024/1/20 21:47
*/
public class DateFactoryBean implements FactoryBean<Date> {
// DateFactoryBean这个工厂Bean协助Spring创建普通的Bean:Date
private String strDate;
public DateFactoryBean(String strDate) {
this.strDate = strDate;
}
public Date getObject() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(strDate);
return date;
}
public Class<?> getObjectType() {
return Date.class;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.f.spring6.bean.Student">
<property name="birth" ref="date"/>
</bean>
<!--通过DateFactoryBean这个工厂Bean来帮助我们创建Date Bean-->
<bean id="date" class="com.f.spring6.bean.DateFactoryBean">
<!--只要按yyyy-MM-dd格式输入,就能创建Date对象,因为我们已经在DateFactoryBean中定义了-->
<constructor-arg name="strDate" value="2000-10-10"/>
</bean>
</beans>1
2
3
4
5
6
public void testInstantiation5() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Student student = applicationContext.getBean("student", Student.class);
System.out.println(student);
}从
DateFactoryBean到Date的过程为:通过构造方法创建
DateFactoryBean这个工厂Bean,并且根据传入的参数<constructor-arg name="strDate" value="2000-10-10"/>给
DateFactoryBean的strDate赋值。Spring 容器会调用工厂 Bean 的
getObject()方法,在这个方法中,我们根据strDate创建Date对象。DateFactoryBean所创建的Date对象即为赋给Student对象的DateBean。