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) |