传统 Spring 框架,XML 配置 Bean 的方式

传统 Spring 框架(非 Spring Boot)中,常用XML配置Bean,大体有下面几种方式。

配置方式 适用场景 优点 缺点
无参构造器 最常见 简单 无法控制初始化
有参构造器 强制依赖 不可变对象 构造器复杂时冗长
Setter 注入 可选依赖 灵活、可重配置 对象可能不完整
静态工厂 单例对象 统一管理创建 代码侵入
实例工厂 复杂创建逻辑 可配置工厂 需要额外的工厂 Bean
集合注入 集合属性 直观 XML 冗长

1. 基本 Bean 定义

无参构造器

xml 复制代码
<!-- 使用默认无参构造器 -->
<bean id="userService" class="com.example.service.UserService"/>
java 复制代码
public class UserService {
    public UserService() {
        System.out.println("UserService 已创建");
    }
    public void doSomething() {
        System.out.println("执行业务逻辑");
    }
}

有参构造器注入

xml 复制代码
<bean id="orderService" class="com.example.service.OrderService">
    <!-- 基本类型注入 -->
    <constructor-arg value="100"/>
    <!-- 引用其他 Bean -->
    <constructor-arg ref="userService"/>
    <!-- 指定参数索引或类型 -->
    <constructor-arg index="2" value="张三"/>
    <constructor-arg type="java.lang.String" value="李四"/>
</bean>
java 复制代码
public class OrderService {
    private int id;
    private UserService userService;
    private String name;
    
    public OrderService(int id, UserService userService, String name) {
        this.id = id;
        this.userService = userService;
        this.name = name;
    }
}

2. 属性注入(Setter 方法)

xml 复制代码
<bean id="dataSource" class="com.example.DataSource">
    <!-- 基本类型 -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
    
    <!-- 引用其他 Bean -->
    <property name="connectionPool" ref="poolConfig"/>
    
    <!-- 内部 Bean -->
    <property name="config">
        <bean class="com.example.Config">
            <property name="maxActive" value="100"/>
        </bean>
    </property>
</bean>
java 复制代码
public class DataSource {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private ConnectionPool connectionPool;
    private Config config;
    
    // 必须提供 setter 方法
    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }
    // ... 其他 setter 方法
}

3. 静态工厂方法

xml 复制代码
<bean id="dateFormat" class="java.text.SimpleDateFormat" 
      factory-method="getDateInstance"/>

<bean id="calendar" class="java.util.Calendar" 
      factory-method="getInstance"/>

<!-- 带参数的静态工厂 -->
<bean id="numberFormat" class="java.text.NumberFormat" 
      factory-method="getCurrencyInstance"/>
java 复制代码
// 自定义静态工厂
public class ServiceFactory {
    public static UserService createUserService() {
        UserService service = new UserService();
        service.setName("从静态工厂创建");
        return service;
    }
    
    public static OrderService createOrderService(int type) {
        if (type == 1) {
            return new OrderService(100);
        }
        return new OrderService(200);
    }
}

// XML 配置
<bean id="userService" class="com.example.ServiceFactory" 
      factory-method="createUserService"/>

<!-- 带参数的静态工厂方法 -->
<bean id="orderService" class="com.example.ServiceFactory" 
      factory-method="createOrderService">
    <constructor-arg value="1"/>
</bean>

4. 实例工厂方法

xml 复制代码
<!-- 先定义工厂 Bean -->
<bean id="serviceFactory" class="com.example.InstanceServiceFactory"/>

<!-- 通过工厂 Bean 创建实例 -->
<bean id="userService" factory-bean="serviceFactory" 
      factory-method="createUserService"/>

<!-- 带参数的实例工厂方法 -->
<bean id="orderService" factory-bean="serviceFactory" 
      factory-method="createOrderService">
    <constructor-arg value="500"/>
</bean>
java 复制代码
public class InstanceServiceFactory {
    public UserService createUserService() {
        return new UserService();
    }
    
    public OrderService createOrderService(double amount) {
        return new OrderService(amount);
    }
}

5. 集合属性注入

xml 复制代码
<bean id="collectionBean" class="com.example.CollectionBean">
    <!-- List 类型 -->
    <property name="list">
        <list>
            <value>item1</value>
            <value>item2</value>
            <ref bean="userService"/>
        </list>
    </property>
    
    <!-- Set 类型 -->
    <property name="set">
        <set>
            <value>value1</value>
            <value>value2</value>
            <ref bean="orderService"/>
        </set>
    </property>
    
    <!-- Map 类型 -->
    <property name="map">
        <map>
            <entry key="key1" value="value1"/>
            <entry key="key2" value-ref="userService"/>
            <entry key="key3">
                <bean class="com.example.Config"/>
            </entry>
        </map>
    </property>
    
    <!-- Properties 类型 -->
    <property name="properties">
        <props>
            <prop key="driver">com.mysql.jdbc.Driver</prop>
            <prop key="url">jdbc:mysql://localhost:3306/db</prop>
        </props>
    </property>
</bean>

6. 作用域配置

xml 复制代码
<!-- 单例(默认) -->
<bean id="singletonBean" class="com.example.SingletonBean" scope="singleton"/>

<!-- 原型(每次获取都创建新实例) -->
<bean id="prototypeBean" class="com.example.PrototypeBean" scope="prototype"/>

<!-- Web 应用中的作用域 -->
<bean id="requestBean" class="com.example.RequestBean" scope="request"/>
<bean id="sessionBean" class="com.example.SessionBean" scope="session"/>
<bean id="applicationBean" class="com.example.ApplicationBean" scope="application"/>

7. 生命周期回调

xml 复制代码
<bean id="lifecycleBean" class="com.example.LifecycleBean" 
      init-method="customInit" 
      destroy-method="customDestroy"/>
java 复制代码
public class LifecycleBean {
    // 配置中指定的初始化方法
    public void customInit() {
        System.out.println("Bean 初始化");
    }
    
    // 配置中指定的销毁方法
    public void customDestroy() {
        System.out.println("Bean 销毁");
    }
}

8. Bean 继承与抽象 Bean

xml 复制代码
<!-- 抽象父 Bean(不会被实例化) -->
<bean id="baseService" abstract="true">
    <property name="commonProperty" value="common"/>
    <property name="dataSource" ref="dataSource"/>
</bean>

<!-- 子 Bean 继承父配置 -->
<bean id="userService" class="com.example.UserService" parent="baseService">
    <property name="specificProperty" value="specific"/>
</bean>

<bean id="orderService" class="com.example.OrderService" parent="baseService">
    <property name="anotherProperty" value="another"/>
</bean>

9. 延迟初始化

xml 复制代码
<!-- 延迟初始化:只有在首次使用时才创建 -->
<bean id="lazyBean" class="com.example.LazyBean" lazy-init="true"/>

<!-- 全局配置所有 Bean 延迟初始化 -->
<beans default-lazy-init="true">
    <bean id="bean1" class="com.example.Bean1"/>
    <bean id="bean2" class="com.example.Bean2"/>
</beans>

10. 别名配置

xml 复制代码
<!-- 定义主名称和别名 -->
<bean id="userService" name="userServiceAlias, service1, service2" 
      class="com.example.UserService"/>

<!-- 单独定义别名 -->
<alias name="userService" alias="anotherAlias"/>

11. 包扫描与注解支持

xml 复制代码
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.example"/>

<!-- 等同于上面的简写 -->
<context:annotation-config/>
<context:component-scan base-package="com.example"/>

<!-- 配置属性占位符 -->
<context:property-placeholder location="classpath:jdbc.properties"/>

<!-- 加载多个配置文件 -->
<context:property-placeholder 
    location="classpath:db.properties, classpath:redis.properties"/>

12. 导入其他配置文件

xml 复制代码
<!-- applicationContext.xml -->
<beans>
    <!-- 导入其他 XML 配置文件 -->
    <import resource="classpath:dao-config.xml"/>
    <import resource="classpath:service-config.xml"/>
    <import resource="classpath:web-config.xml"/>
    
    <!-- 使用通配符 -->
    <import resource="classpath*:config/spring-*.xml"/>
</beans>

13. 完整示例:三层架构配置

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <!-- 加载属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    
    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    
    <!-- 配置 JdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- DAO 层 -->
    <bean id="userDao" class="com.example.dao.UserDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
    
    <!-- Service 层 -->
    <bean id="userService" class="com.example.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>
    
    <!-- 事务管理器 -->
    <bean id="transactionManager" 
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- 开启事务注解支持 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <!-- 开启包扫描(使用注解方式) -->
    <context:component-scan base-package="com.example"/>
</beans>

14. 加载 XML 配置的方式

java 复制代码
// 方式1:从类路径加载
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

// 方式2:从文件系统加载
ApplicationContext context = new FileSystemXmlApplicationContext("/config/applicationContext.xml");

// 方式3:加载多个配置文件
ApplicationContext context = new ClassPathXmlApplicationContext(
    "dao-config.xml", "service-config.xml", "web-config.xml"
);

// 方式4:使用通配符
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:config/spring-*.xml");

// 方式5:构建器方式
ApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("applicationContext.xml");
context.refresh();

// 获取 Bean 实例
UserService userService = context.getBean("userService", UserService.class);
OrderService orderService = context.getBean(OrderService.class);

传统 Spring 项目中,通常会混用 XML 和注解 :Bean 定义用 XML,Bean 内部的依赖注入用 @Autowired/@Resource 注解。

相关推荐
未秃头的程序猿9 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·后端·ai编程
程序员老乔9 小时前
03-Spring-Security-JWT认证
java·后端·spring
希望永不加班9 小时前
SpringBoot 消费者并发控制:线程池配置
java·spring boot·后端·spring
MateCloud微服务9 小时前
从 Karpathy 加入 Anthropic 到 Claude Agent 化:MateClaw 为什么要做企业级 Agent Runtime
java·java agent·mateclaw·mateclaw agent·mc runtime·mc harness·mateclaw open
Yolanda949 小时前
【编程学习】复盘经典 VB OOP 示例:推翻旧认知,重学面向对象
java·面向对象
Y敲键盘的地方9 小时前
第9章 工具调用循环——Agent的行动闭环
java·服务器·前端
专注写bug9 小时前
Java线程池——ThreadLocal上下文污染问题
java
武子康9 小时前
Java-09 深入浅出 MyBatis 注解开发详解:从 CRUD 到复杂关系映射
java·后端·spring
Amctwd9 小时前
【后端】多个后端系统,如何共用一套登录状态?单点登录详解
java