【Spring】Bean 的实例化方式

Spring 为 Bean 提供了多种实例化方式,通常包括4种方式

也就是说在 Spring 中为 Bean 对象的创建准备了多种方案,目的是:更加灵活

  • 第一种:通过构造方法实例化

  • 第二种:通过简单工厂模式实例化

  • 第三种:通过 factory-bean 实例化

  • 第四种:通过 FactoryBean 接口实例化

 

一、通过构造方法实例化 

public class SpringBean {
    public SpringBean(){
        System.out.println("SpringBean 的无参数构造方法执行.......");
    }
}
<!--
    Spring 提供的实例化方式
        第一种:在Spring配置文件中直接配置类全路径,Spring会自动调用该类的无参数构造方法来实例化Bean
-->
<bean id="springBean" class="org.qiu.spring.bean.SpringBean"/>
@Test
public void testInstantiationOne(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    SpringBean springBean = applicationContext.getBean("springBean", SpringBean.class);
    System.out.println(springBean);
}

运行结果: 

 

二、通过简单工厂模式实例化 

public class Star {
    public Star(){
        System.out.println("Star 的无参数构造方法执行......");
    }
}
public class StarFactory {
    public static Star get(){
        // 这个 Star 实际上创建的时候还是我们自己 new 的对象
        return new Star();
    }
}
<!--
    Spring 提供的实例化方式
        第二种:简单工厂模式。需要在Spring配置文件中告诉Spring框架,调用哪个类的哪个方法获取Bean
        factory-method : 指定工厂类中的静态方法,告诉Spring框架,调用这个方法可以获取Bean
-->
<bean id="starBean" class="org.qiu.spring.bean.StarFactory" factory-method="get"/>
@Test
public void testtestInstantiationTwo(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Star star = applicationContext.getBean("starBean", Star.class);
    System.out.println(star);
}

运行结果:

 

三、通过 factory-bean 实例化

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

public class Gun{
    public Gun() {
        System.out.println("Gun 的无参数构造方法执行......");
    }
}
public class GunFactory{
    public Gun get(){
        return new Gun();
    }
}
<!--
    Spring 提供的实例化方式
        第三种:通过工厂方法模式
-->
<bean id="gunFactory" class="org.qiu.spring.bean.GunFactory"/>
<bean id="gun" factory-bean="gunFactory" factory-method="get"/>
@Test
public void testtestInstantiationThree(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Gun gun = applicationContext.getBean("gun", Gun.class);
    System.out.println(gun);
}

运行结果:

 

四、通过 FactoryBean 接口实例化 

以上的第三种方式中,factory-bean 是我们自定义的,factory-method 也是我们自己定义的

在 Spring 中,当你编写的类直接实现 FactoryBean 接口之后,factory-bean 不需要指定了,factory-method 也不需要指定了

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

package org.qiu.spring.bean;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.bean
 * @date 2022-11-10-22:15
 * @since 1.0
 */
public class Person {
    public Person() {
        System.out.println("Person 的无参数构造方法执行......");
    }
}
package org.qiu.spring.bean;

import org.springframework.beans.factory.FactoryBean;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.bean
 * @date 2022-11-10-22:16
 * @since 1.0
 */
public class PersonFactoryBean implements FactoryBean<Person> {
    @Override
    public Person getObject() throws Exception {
        // 最终这个 Bean 的创建还是程序员自己 new 的
        return new Person();
    }

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

    /**
     * 这个方法 FactoryBean 接口有默认实现
     *      default boolean isSingleton() {
     *          return true;
     *      }
     * 即获取的 Bean 默认情况下是单例的
     * 若需要修改为多例,修改为 return false 即可
     */
    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}
<!--
    Spring 提供的实例化方式
        第四种:通过 FactoryBean 接口来实现,实际上简化了第三种方式
        通过 factoryBean 这个工厂 Bean 主要是想对普通 Bean 进行加工处理
-->
<bean id="personBean" class="org.qiu.spring.bean.PersonFactoryBean"/>
@Test
public void testInstantiationFour(){
    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);
}

运行结果:

FactoryBean 在 Spring 中是一个接口,被称为 “工厂Bean”。“工厂Bean”是一种特殊的 Bean。所有的“工厂Bean”都是用来协助Spring 框架来创建其他 Bean 对象的

 

五、BeanFactory 和 FactoryBean 的区别 

BeanFactory:

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

BeanFactory 是工厂


FactoryBean:

FactoryBean:它是一个Bean,是一个能够辅助 Spring 实例化其它 Bean 对象的一个 Bean

在 Spring 中,Bean可以分为两类:

  • 第一类:普通 Bean

  • 第二类:工厂 Bean(记住:工厂 Bean 也是一种 Bean,只不过这种 Bean 比较特殊,它可以辅助 Spring 实例化其它 Bean 对象)

 

六、注入自定义 Date 

前面说过,java.util.Date 在 Spring 中被当做简单类型,简单类型在注入的时候可以直接使用 value 属性或 value 标签来完成。但我们之前已经测试过了,对于 Date 类型来说,采用 value 属性或 value 标签赋值的时候,对日期字符串的格式要求非常严格,必须是这种格式的:Mon Oct 10 14:30:26 CST 2022,其他格式是不会被识别的。如以下代码:  

package org.qiu.spring.bean;

import java.util.Date;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.bean
 * @date 2022-11-10-22:34
 * @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 +
                '}';
    }
}
package org.qiu.spring.bean;

import org.springframework.beans.factory.FactoryBean;

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

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.bean
 * @date 2022-11-10-22:41
 * @since 1.0
 */
public class DateFactoryBean implements FactoryBean<Date> {

    private String strDate;

    public DateFactoryBean(String strDate) {
        this.strDate = strDate;
    }

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

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}
<!--
    1、将 value 的值通过 DateFactoryBean 的构造方法 DateFactoryBean(String strDate) 赋值给 DateFactoryBean 的 date 属性
    2、DateFactoryBean 实现了 FactoryBean 接口,Spring 会自动调用 getObject 方法
    3、getObject 中对第一步注入的字符串(date字符串)进行格式化并返回一个自定义格式的 Date 对象
    4、将上一步的 Date 对象注入给 Student 这个 Bean 的 birth 属性
-->
<bean id="date" class="org.qiu.spring.bean.DateFactoryBean">
    <constructor-arg index="0" value="2000-01-01"/>
</bean>

<bean id="student" class="org.qiu.spring.bean.Student">
    <property name="birth" ref="date"/>
</bean>
@Test
public void testDate(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Student student = applicationContext.getBean("student", Student.class);
    System.out.println(student);
}

运行结果: 

 

一  叶  知  秋,奥  妙  玄  心

  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qx_java_1024

祝老板生意兴隆,财源广进!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值