Spring 实例化bean有几种方式?

Spring 实例化 Bean 是 IoC 容器的核心能力之一,主要有 6 种常见方式,我会从新手易懂的角度,由基础到进阶逐一讲解,并配合代码示例,让你清晰理解每种方式的使用场景和实现逻辑。

一、核心实例化方式(附代码示例)

1. 构造器实例化(最常用)

这是 Spring 默认的实例化方式,IoC 容器通过调用 Bean 的无参构造器创建实例(如果有参构造器,需通过配置指定参数)。

  • 适用场景:绝大多数普通业务 Bean(如 Service、Controller)。

  • 代码示例:

    复制代码
    // 1. 定义普通类(无参构造器默认存在,无需显式写)
    public class UserService {
        public UserService() {
            System.out.println("UserService 无参构造器执行");
        }
        
        public void sayHello() {
            System.out.println("Hello, Spring!");
        }
    }
    
    // 2. Spring 配置(XML 方式)
    <!-- applicationContext.xml -->
    <bean id="userService" class="com.example.UserService"/>
    
    // 3. 测试代码
    public class Test {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserService userService = (UserService) context.getBean("userService");
            userService.sayHello(); // 输出:UserService 无参构造器执行 + Hello, Spring!
        }
    }

    如果是有参构造器,XML 配置需指定参数:

    xml

    复制代码
    <!-- 有参构造器实例化 -->
    <bean id="userService" class="com.example.UserService">
        <constructor-arg value="张三"/> <!-- 对应构造器的参数 -->
    </bean>
2. 静态工厂方法实例化

通过调用静态方法返回 Bean 实例,适用于需要统一控制实例创建逻辑的场景(如工具类、单例对象)。

  • 适用场景:第三方类库、自定义单例工厂。

  • 代码示例:

    复制代码
    // 1. 定义工厂类(包含静态方法)
    public class UserServiceFactory {
        // 静态工厂方法,返回 UserService 实例
        public static UserService createUserService() {
            return new UserService();
        }
    }
    
    // 2. Spring 配置
    <bean id="userService" class="com.example.UserServiceFactory" 
          factory-method="createUserService"/> <!-- 指定静态工厂方法 -->
    
    // 3. 测试(和构造器方式一致,Spring 会调用 createUserService() 创建实例)
3. 实例工厂方法实例化

通过调用非静态方法(即先创建工厂 Bean 实例,再调用其方法)返回 Bean 实例,适用于工厂类需要维护状态的场景。

  • 适用场景:工厂类需要依赖其他 Bean、或需要多实例工厂。

  • 代码示例:

    复制代码
    // 1. 定义实例工厂类(非静态方法)
    public class UserServiceInstanceFactory {
        public UserService createUserService() {
            return new UserService();
        }
    }
    
    // 2. Spring 配置(先定义工厂 Bean,再通过工厂 Bean 调用方法)
    <bean id="userServiceFactory" class="com.example.UserServiceInstanceFactory"/>
    <bean id="userService" factory-bean="userServiceFactory" 
          factory-method="createUserService"/>
4. FactoryBean 接口实例化(进阶)

这是 Spring 提供的专用工厂接口(注意和上面的 "工厂方法" 区分),实现该接口可以自定义 Bean 的创建逻辑,还能控制 Bean 的初始化、销毁。

  • 核心方法:

    • getObject():返回 Bean 实例;
    • getObjectType():返回 Bean 的类型;
    • isSingleton():是否单例(默认 true)。
  • 适用场景:复杂对象创建(如数据源、MyBatis 的 SqlSessionFactory)。

  • 代码示例:

    复制代码
    // 1. 实现 FactoryBean 接口
    public class UserServiceFactoryBean implements FactoryBean<UserService> {
        @Override
        public UserService getObject() throws Exception {
            return new UserService(); // 自定义创建逻辑
        }
    
        @Override
        public Class<?> getObjectType() {
            return UserService.class;
        }
    
        // 可选:指定是否单例(默认 true)
        @Override
        public boolean isSingleton() {
            return true;
        }
    }
    
    // 2. Spring 配置
    <bean id="userService" class="com.example.UserServiceFactoryBean"/>
    
    // 3. 测试(Spring 会自动调用 getObject() 获取实例)
5. 注解驱动实例化(主流)

基于注解的方式是现代 Spring 开发的主流,替代 XML 配置,核心注解包括:

  • @Component:通用注解(标注普通 Bean);

  • @Service:标注业务层 Bean;

  • @Controller:标注控制层 Bean;

  • @Repository:标注数据访问层 Bean;

  • @Configuration + @Bean:标注配置类,通过方法返回 Bean 实例。

  • 代码示例(@Component 方式):

    复制代码
    // 1. 标注注解
    @Service // 等同于在 XML 中定义 Bean
    public class UserService {
        public void sayHello() {
            System.out.println("Hello, Annotation!");
        }
    }
    
    // 2. 开启注解扫描(XML 或配置类)
    <!-- XML 方式开启扫描 -->
    <context:component-scan base-package="com.example"/>
    
    // 或配置类方式(推荐)
    @Configuration
    @ComponentScan("com.example") // 扫描指定包下的注解 Bean
    public class SpringConfig {}
    
    // 3. 测试
    public class Test {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
            UserService userService = context.getBean(UserService.class);
            userService.sayHello(); // 输出:Hello, Annotation!
        }
    }
  • 代码示例(@Configuration + @Bean 方式):

    复制代码
    // 1. 配置类中定义 Bean
    @Configuration
    public class SpringConfig {
        // 方法返回值即为 Bean 实例,方法名默认是 Bean 的 id
        @Bean
        public UserService userService() {
            return new UserService();
        }
    }
    
    // 2. 测试(直接获取 Bean)
6. 通过 BeanDefinition 手动实例化(底层)

这是最底层的方式,直接操作 Spring 的 BeanDefinition(Bean 的定义元数据),通过编程式方式向容器注册 Bean,适用于框架开发或动态创建 Bean。

  • 适用场景:自定义 Spring 扩展、动态生成 Bean。

  • 代码示例:

    复制代码
    public class Test {
        public static void main(String[] args) {
            // 1. 创建 BeanFactory 容器
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            
            // 2. 构建 BeanDefinition(定义 Bean 的元数据)
            BeanDefinition beanDefinition = BeanDefinitionBuilder
                    .genericBeanDefinition(UserService.class)
                    .getBeanDefinition();
            
            // 3. 注册 BeanDefinition 到容器
            beanFactory.registerBeanDefinition("userService", beanDefinition);
            
            // 4. 获取 Bean 实例
            UserService userService = beanFactory.getBean("userService", UserService.class);
            userService.sayHello();
        }
    }

二、不同方式的使用场景总结

表格

实例化方式 核心特点 适用场景
构造器实例化 简单、默认支持 普通业务 Bean(无复杂创建逻辑)
静态工厂方法 统一控制实例创建 第三方类库、单例对象
实例工厂方法 工厂可维护状态、依赖其他 Bean 需多实例工厂、工厂依赖注入
FactoryBean 接口 自定义创建逻辑、控制初始化 复杂对象(数据源、SqlSessionFactory)
注解驱动实例化 简洁、主流 现代 Spring 项目(Spring Boot)
BeanDefinition 手动 底层、灵活 框架开发、动态创建 Bean

总结

  1. 日常开发优先用注解@Service/@Controller/@Bean 是 Spring Boot 主流,简洁高效;
  2. 基础方式是构造器:Spring 默认通过无参构造器实例化 Bean,是所有方式的基础;
  3. 复杂场景用工厂FactoryBean 适合复杂对象创建,静态 / 实例工厂适合统一控制实例逻辑。

核心记住:Spring 实例化 Bean 的本质是 IoC 容器根据 Bean 的定义(XML / 注解 / BeanDefinition),调用对应的创建逻辑(构造器 / 工厂方法)生成实例,最终将实例存入容器供使用。

相关推荐
OtIo TALL3 小时前
redis7 for windows的安装教程
java
2601_949817723 小时前
Spring Boot3.3.X整合Mybatis-Plus
spring boot·后端·mybatis
uNke DEPH3 小时前
Spring Boot的项目结构
java·spring boot·后端
xixingzhe24 小时前
idea启动vue项目
java·vue.js·intellij-idea
zhenxin01224 小时前
Spring Boot 3.x 系列【3】Spring Initializr快速创建Spring Boot项目
spring boot·后端·spring
wzl202612134 小时前
企业微信定时群发技术实现与实操指南(原生接口+工具落地)
java·运维·前端·企业微信
凌波粒4 小时前
Java 8 “新”特性详解:Lambda、函数式接口、Stream、Optional 与方法引用
java·开发语言·idea
曹牧4 小时前
Eclipse:悬停提示(Hover)
java·ide·eclipse
前端一小卒4 小时前
前端工程师的全栈焦虑,我用 60 天治好了
前端·javascript·后端
不停喝水4 小时前
【AI+Cursor】 告别切图仔,拥抱Vibe Coding: AI + Cursor 开启多模态全栈新纪元 (1)
前端·人工智能·后端·ai·ai编程·cursor