Spring实例化bean有几种方式

0 阅读4分钟

Spring 实例化 Bean 主要有三种核心方式:构造器实例化、静态工厂方法实例化和实例工厂方法实例化,其中构造器实例化是最常用的方式。

1. 构造器实例化(默认方式)

Spring 容器通过调用 Bean 类的构造器(默认无参构造器或有参构造器)来创建实例,这是最基础、最常用的方式。

无参构造器实例化:Bean 类必须提供无参构造器(若未显式定义任何构造器,Java 会默认生成)。

<!-- 配置文件方式 -->
<bean id="userService" class="com.example.UserService"/>
// 注解方式(@Component、@Service等)
@Service
public class UserService {
    // 无参构造器(默认存在)
}

有参构造器实例化:需在配置中指定构造器参数,Spring 会根据参数类型、索引或名称匹配对应的构造器。

<bean id="user" class="com.example.User">
    <constructor-arg name="id" value="1"/>
    <constructor-arg name="name" value="Alice"/>
</bean>

2. 静态工厂方法实例化

通过调用一个静态工厂类的静态方法来创建 Bean 实例,适用于实例创建逻辑复杂,需封装在工厂中的场景。

1.定义静态工厂类和静态方法。
    
public class UserStaticFactory {
    // 静态工厂方法
    public static User createUser() {
        return new User(2, "Bob");
    }
}

2.在配置中指定工厂类和静态方法。

<bean id="userByStaticFactory" 
      class="com.example.UserStaticFactory" 
      factory-method="createUser"/>
  

3. 实例工厂方法实例化

通过调用一个非静态工厂类的实例方法来创建 Bean 实例,工厂类本身也需要作为一个 Bean 被 Spring 管理。

1.定义实例工厂类和实例方法。

public class UserInstanceFactory {
    // 实例工厂方法(非静态)
    public User createUser() {
        return new User(3, "Charlie");
    }
}

2.先配置工厂 Bean,再配置目标 Bean,指定工厂 Bean 和实例方法。

<!-- 配置实例工厂Bean -->
<bean id="userInstanceFactory" class="com.example.UserInstanceFactory"/>
<!-- 通过工厂Bean的实例方法创建目标Bean -->
<bean id="userByInstanceFactory" 
      factory-bean="userInstanceFactory" 
      factory-method="createUser"/>

4.factoryBean

FactoryBean 是 Spring 提供的一种特殊 Bean,它本身不直接作为业务对象,而是专门用于创建和管理其他 Bean 实例的“工厂”。与普通实例工厂方法不同,FactoryBean 是 Spring 容器级别的扩展点,使用更灵活。

核心原理

当 Spring 容器发现一个 Bean 的类型是 FactoryBean 时,它不会直接返回该 Bean 本身,而是会调用其 getObject() 方法,并将该方法的返回值作为最终的 Bean 实例返回给使用者。

实现步骤

实现 FactoryBean 接口来实例化 Bean,通常分为以下3步:

1.实现 FactoryBean 接口

自定义一个类实现 org.springframework.beans.factory.FactoryBean 接口,并实现其3个核心方法。

import org.springframework.beans.factory.FactoryBean;

// T 为要创建的目标 Bean 类型
public class UserFactoryBean implements FactoryBean<User> {

    /**
     * 核心方法:返回目标 Bean 的实例
     * 复杂的创建逻辑(如依赖注入、初始化配置)可在此实现
     */
    @Override
    public User getObject() throws Exception {
        User user = new User();
        user.setId(4);
        user.setName("David");
        // 模拟复杂逻辑:如调用其他服务、读取配置等
        return user;
    }

    /**
     * 返回目标 Bean 的类型
     */
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    /**
     * 指定目标 Bean 是否为单例(默认 true)
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

2.配置 FactoryBean 到 Spring 容器

将自定义的 FactoryBean 本身作为一个普通 Bean 配置到 Spring 中(XML 或注解方式均可)。

<!-- XML 配置方式 -->
<bean id="userFactoryBean" class="com.example.UserFactoryBean"/>
// 注解配置方式(@Component)
@Component("userFactoryBean")
public class UserFactoryBean implements FactoryBean<User> {
    // 实现同上
}

3.获取目标 Bean

从 Spring 容器中获取的并非 UserFactoryBean 实例,而是其 getObject() 方法返回的 User 实例。

@Test
public void test6() {
  // 测试类
  //通过注解的方式生成bean的测试
  ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

  User user = (User) context.getBean("myFactoryBean");
  System.out.println(user);
  //获取工厂本身
  UserFactoryBean userFactoryBean = (UserFactoryBean) context.getBean("&myFactoryBean");
  System.out.println(userFactoryBean);

}

关键特点

  • 隐藏创建细节:将目标 Bean 复杂的创建逻辑(如依赖组装、多步骤初始化)封装在 FactoryBean 中,使用者无需关心。

  • 容器集成度高:FactoryBean 本身受 Spring 容器管理,可以注入其他 Bean、感知容器生命周期(如实现 InitializingBean)。

  • 单例/多例控制:通过 isSingleton() 方法可灵活控制目标 Bean 是单例(默认)还是多例。

典型应用场景

  • 整合第三方框架:如 MyBatis 中的 SqlSessionFactoryBean,Spring 整合 Redis 时的 RedisTemplate 工厂等。

  • 创建复杂实例:当一个 Bean 的创建需要大量配置(如读取配置文件、调用多个服务)时,使用 FactoryBean 封装逻辑。

总结

实例化方式核心特点适用场景
构造器实例化简单直接,Spring 默认方式大多数普通 Bean,无复杂创建逻辑
静态工厂实例化通过静态方法创建,工厂无需实例化复杂创建逻辑,需封装且工厂无需状态
实例工厂实例化通过实例方法创建,工厂需被 Spring 管理复杂创建逻辑,工厂本身需要维护状态
factoryBean实例化实现 FactoryBean 接口能感知 Spring 容器,可注入其他 Bean,配置简单,只需注册 FactoryBean 本身,可集成 Spring 生命周期接口(如 DisposableBean)