Skip to content

07 Bean的实例化方式

Spring 为 Bean 提供了多种实例化方式,通常包括 4 种方式。(也就是说在 Spring 中为 Bean 对象的创建准备了多种方案,目的是:更加灵活) - 第一种:通过构造方法实例化 - 第二种:通过简单工厂模式实例化 - 第三种:通过 factory-bean 实例化 - 第四种:通过 FactoryBean 接口实例化


7.1 通过构造方法实例化

我们之前一直使用的就是这种方式。默认情况下,会调用 Bean 的无参数构造方法。

```java title:User package com.powernode.spring6.bean;

/** * @author 动力节点 * @version 1.0 * @className User * @since 1.0 */ public class User { public User() { System.out.println("User类的无参数构造方法执行。"); } }

```xml title:spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="userBean" class="com.powernode.spring6.bean.User"/>

</beans>   

```java title:SpringInstantiationTest package com.powernode.spring6.test;

import com.powernode.spring6.bean.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;

/** * @author 动力节点 * @version 1.0 * @className SpringInstantiationTest * @since 1.0 */ public class SpringInstantiationTest {

@Test
public void testConstructor(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    User user = applicationContext.getBean("userBean", User.class);
    System.out.println(user);
}

} ``` 执行结果: ![[07.01-1.png]]


7.2 通过简单工厂模式实例化

第一步:定义一个 Bean java title:Vip package com.powernode.spring6.bean; /** * @author 动力节点 * @version 1.0 * @className Vip * @since 1.0 */ public class Vip { }

第二步:编写简单工厂模式当中的工厂类 ```java title:VipFactory package com.powernode.spring6.bean;

/** * @author 动力节点 * @version 1.0 * @className VipFactory * @since 1.0 */ public class VipFactory { public static Vip get(){ return new Vip(); } }

第三步:在 Spring 配置文件中指定创建该 Bean 的方法(使用 factory-method 属性指定)
```xml title:spring.xml

第四步:编写测试程序 ```java title:testSimpleFactory @Test public void testSimpleFactory(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Vip vip = applicationContext.getBean("vipBean", Vip.class); System.out.println(vip); }

执行结果:
![[07.02-1.png]]


---
## 7.3 通过 factory-bean 实例化

这种方式本质上是:通过工厂方法模式进行实例化。

第一步:定义一个 Bean
```java title:Order
package com.powernode.spring6.bean;

/**
* @author 动力节点
* @version 1.0
* @className Order
* @since 1.0
*/
public class Order {
}

第二步:定义具体工厂类,工厂类中定义实例方法 ```java title:OrderFactory package com.powernode.spring6.bean;

/** * @author 动力节点 * @version 1.0 * @className OrderFactory * @since 1.0 */ public class OrderFactory { public Order get(){ return new Order(); } }

第三步:在 Spring 配置文件中指定 `factory-bean` 以及 `factory-method`
```xml title:spring.xml
<bean id="orderFactory" class="com.powernode.spring6.bean.OrderFactory"/>
<bean id="orderBean" factory-bean="orderFactory" factory-method="get"/>

第四步:编写测试程序 ```java title:testSelfFactoryBean @Test public void testSelfFactoryBean(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Order orderBean = applicationContext.getBean("orderBean", Order.class); System.out.println(orderBean); }

执行结果:
![[07.03-1.png]]


---
## 7.4 通过 FactoryBean 接口实例化

以上的第三种方式中,factory-bean 是我们自定义的,factory-method 也是我们自己定义的。
在 Spring 中,当你编写的类直接实现 FactoryBean 接口之后,factory-bean 不需要指定了,factory-method 也不需要指定了。

**factory-bean 会自动指向实现 FactoryBean 接口的类,factory-method 会自动指向 `getObject ()` 方法。**

第一步:定义一个 Bean
```java title:Person
package com.powernode.spring6.bean;

/**
* @author 动力节点
* @version 1.0
* @className Person
* @since 1.0
*/
public class Person {
}

第二步:编写一个类实现 FactoryBean 接口 ```java title:PersonFactoryBean package com.powernode.spring6.bean;

import org.springframework.beans.factory.FactoryBean;

/** * @author 动力节点 * @version 1.0 * @className PersonFactoryBean * @since 1.0 */ public class PersonFactoryBean implements FactoryBean {

@Override
public Person getObject() throws Exception {
    return new Person();
}

@Override
public Class getObjectType() {
    return null;
}

@Override
public boolean isSingleton() {
    // true表示单例
    // false表示原型
    return true;
}

} 第三步:在 Spring 配置文件中配置 FactoryBeanxml title:spring.xml ```

测试程序: ```java title:testFactoryBean @Test public void testFactoryBean(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Person personBean = applicationContext.getBean("personBean", Person.class); System.out.println(personBean);

Person personBean2 = applicationContext.getBean("personBean", Person.class);
System.out.println(personBean2);

} ``` 执行结果: ![[07.04-1.webp]] FactoryBean 在 Spring 中是一个接口。被称为“工厂 Bean”。“工厂 Bean”是一种特殊的 Bean。所有的“工厂 Bean”都是用来协助 Spring 框架来创建其他 Bean 对象的。


7.5 BeanFactory 和 FactoryBean 的区别

7.5.1 BeanFactory

Spring IoC 容器的顶级对象,BeanFactory 被翻译为“Bean 工厂”,在 Spring 的 IoC 容器中,“Bean 工厂”负责创建 Bean 对象。 BeanFactory 是工厂。

7.5.2 FactoryBean

FactoryBean:它是一个 Bean,是一个能够辅助 Spring 实例化其它 Bean 对象的一个 Bean。 在 Spring 中,Bean 可以分为两类: - 第一类:普通 Bean - 第二类:工厂 Bean(记住:工厂 Bean 也是一种 Bean,只不过这种 Bean 比较特殊,它可以辅助 Spring 实例化其它 Bean 对象。)


7.6 注入自定义 Date

我们前面说过,java. util. Date 在 Spring 中被当做简单类型,简单类型在注入的时候可以直接使用 value 属性或 value 标签来完成。但我们之前已经测试过了,对于 Date 类型来说,采用 value 属性或 value 标签赋值的时候,对日期字符串的格式要求非常严格,必须是这种格式的:Mon Oct 10 14:30:26 CST 2022。其他格式是不会被识别的。如以下代码: java title:Student package com.powernode.spring6.bean; import java.util.Date; /** * @author 动力节点 * @version 1.0 * @className Student * @since 1.0 */ public class Student { private Date birth; public void setBirth(Date birth) { this.birth = birth; } @Override public String toString() { return "Student{" + "birth=" + birth + '}'; } }

```xml title:spring.xml

```java title:testDate
@Test
public void testDate(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Student studentBean = applicationContext.getBean("studentBean", Student.class);
    System.out.println(studentBean);
}

执行结果: ![[07.06-1.webp]] 如果把日期格式修改一下:

```xml title:spring.xml

执行结果:
![[07.06-2.png]]
这种情况下,我们就可以使用 FactoryBean 来完成这个骚操作。
编写 DateFactoryBean 实现 FactoryBean 接口:

```java title:DateFactoryBean
package com.powernode.spring6.bean;

import org.springframework.beans.factory.FactoryBean;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* @author 动力节点
* @version 1.0
* @className DateFactoryBean
* @since 1.0
*/
public class DateFactoryBean implements FactoryBean {

    // 定义属性接收日期字符串
    private String date;

    // 通过构造方法给日期字符串属性赋值
    public DateFactoryBean(String date) {
        this.date = date;
    }

    @Override
    public Date getObject() throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.parse(this.date);
    }

    @Override
    public Class getObjectType() {
        return null;
    }
}

编写 spring 配置文件:

```xml title:spring.xml

```

执行测试程序: ![[07.06-3.png]]