Bean的实例化方式

1. 通过构造方法实例化(Constructor Instantiation)

这是最常见的方式,Spring通过调用类的构造方法来创建Bean实例。

XML配置示例

<bean id="userDao" class="com.example.UserDao" />
  • Spring容器在加载时调用UserDao无参构造函数进行实例化。
带参数的构造器注入

如果类没有无参构造器,需要传递参数时,可以在XML中使用<constructor-arg>标签。

<bean id="userService" class="com.example.UserService">
    <constructor-arg name="userDao" ref="userDao" />
</bean>

 对应的Java类:

public class UserService {
    private UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}

2. 通过静态工厂方法实例化(Static Factory Method)

使用静态方法创建Bean实例,适用于无法直接通过构造器创建的对象。

XML配置示例

<bean id="connection" class="com.example.ConnectionFactory" 
      factory-method="createConnection" />

对应的Java类:

public class ConnectionFactory {
    public static Connection createConnection() {
        return new Connection();
    }
}

Spring容器会调用ConnectionFactory.createConnection()返回Connection对象。

3. 通过实例工厂方法实例化(Instance Factory Method)

使用已经创建的工厂实例来创建Bean。

XML配置示例

<bean id="factory" class="com.example.ConnectionFactory" />

<bean id="connection" factory-bean="factory" 
      factory-method="getConnection" />

 对应的Java类:

public class ConnectionFactory {
    public Connection getConnection() {
        return new Connection();
    }
}

Spring首先实例化ConnectionFactory对象,然后调用其getConnection()方法创建Connection实例。

4. 通过工厂Bean(FactoryBean接口)实例化

Spring提供了FactoryBean接口,用于更复杂的对象创建逻辑。实现此接口的类会被Spring识别为工厂。它允许开发者通过实现 FactoryBean 接口,来自定义 Bean 的实例化逻辑。当需要创建一个复杂对象或对象的创建过程需要包含一些逻辑操作时,FactoryBean 是非常有用的。

FactoryBean接口详解

FactoryBean<T> 是一个泛型接口,其中 T 是由该工厂创建的对象类型。实现 FactoryBean 接口的类可以被 Spring 容器用作工厂。其中,T 是一个泛型参数,它表示由工厂创建的对象的类型。在实现 FactoryBean 接口时,需要指定这个泛型参数的具体类型,即工厂将返回的对象的类型

以下是 FactoryBean 接口的关键方法:

  • T getObject(): 定义如何创建和返回一个 Bean 实例。
  • Class<?> getObjectType(): 返回创建的对象类型。
  • boolean isSingleton(): 返回是否创建的对象是单例模式。

Java代码

public class MyBeanFactory implements FactoryBean<MyBean> {
    @Override
    public MyBean getObject() {
        return new MyBean();
    }

    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }

  @Override
    public boolean isSingleton() {
        return true;  // 如果要让 Spring 管理它为单例,可以返回 true
    }
}

 XML配置

<bean id="myBean" class="com.example.MyBeanFactory" />

Spring会调用MyBeanFactorygetObject()方法,返回MyBean实例。

FactoryBean的工作原理

在 Spring 中,当你使用 <bean> 配置来定义一个实现了 FactoryBean 接口的类时,Spring 容器实际上不会直接将这个类本身作为 Bean,而是通过调用 FactoryBeangetObject() 方法来创建 Bean 实例。

BeanFactory和FactoryBean的区别

  • BeanFactorySpring IoC容器的顶级对象 ,是 Spring 的一个核心接口,负责管理和提供 Bean 的实例,是 Spring IoC 容器的基础接口。
  • FactoryBean:是一个特殊的 Bean,用于创建复杂 Bean 实例。它是 Spring 框架中用来实现工厂模式的一种机制,允许自定义创建复杂对象的逻辑。总之,它是一个Bean,是一个能够辅助Spring实例化其它Bean对象的一个Bean。

BeanFactory 详细解释

  • BeanFactory 是 Spring IoC 容器的最基础接口,提供 Bean 的实例管理功能。
  • 它负责 Bean 的创建、管理和生命周期控制
  • 实现类ApplicationContextBeanFactory 的一个子接口,它在 BeanFactory 的基础上增加了更多的企业级功能,通常我们在开发中更多地使用 ApplicationContext

工作方式

  • 延迟加载:默认情况下,BeanFactory 在第一次被请求时才创建 Bean 的实例(延迟加载)。这有助于提高应用的启动速度。
  • 提供方法来获取 Bean,如 getBean(String beanName)
    BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
    MyService myService = (MyService) factory.getBean("myService");
    

FactoryBean 详细解释

  • FactoryBean 是一个实现了 FactoryBean 接口的特殊 Bean,它用于自定义创建复杂对象
  • 实现 FactoryBean 接口的类本质上是一个工厂类,Spring 通过调用 FactoryBeangetObject() 方法,来创建和管理最终的 Bean。
  • FactoryBean 提供了一种方式,可以将对象的创建细节封装到工厂中,这种方式特别适合创建需要复杂初始化过程的 Bean。

核心方法

  • getObject():返回工厂创建的对象。
  • getObjectType():返回创建的对象的类型。
  • isSingleton():指示是否创建单例实例
 FactoryBean 的应用场景:
注入自定义Date:

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

Student类:

package bean;

import java.util.Date;

public class Student {
    private String name;
    private Date birth;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public Student() {
    }

    public Student(String name, Date birth) {
        this.name = name;
        this.birth = birth;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", birth=" + birth +
                '}';
    }
}

如果我们想使用一下形式注入到Date类中,我们就需要使用到FactoryBean

<bean id="studentBean" class="com.powernode.spring6.bean.Student">
  <property name="birth" value="2002-10-10"/>
</bean>

编写DateFactoryBean实现FactoryBean接口:

package com.powernode.spring6.bean;

import org.springframework.beans.factory.FactoryBean;

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

public class DateFactoryBean implements FactoryBean<Date> {

    // 定义属性接收日期字符串
    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配置文件:

<bean id="dateBean" class="com.powernode.spring6.bean.DateFactoryBean">
  <constructor-arg name="date" value="1999-10-11"/>
</bean>

<bean id="studentBean" class="com.powernode.spring6.bean.Student">
  <property name="birth" ref="dateBean"/>
</bean>
  • dateBean 是一个通过工厂创建的日期对象的 Bean。
  • studentBean 是一个 Student 对象,拥有一个名为 birth 的属性,该属性引用了 dateBean
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值