传统 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 注解。

相关推荐
luteres44 分钟前
Spring学习笔记
java·后端·spring
南城以南溫暖如初1471 小时前
从零搭建24小时自助健身系统:技术选型与核心模块实战
java·spring boot·redis·mysql·vue·mybatis
重生之后端学习1 小时前
53. 最大子数组和[中等]✅
java·数据结构·算法·leetcode·职场和发展
XS0301061 小时前
【无标题】
java·tomcat·maven·intellij-idea
陈皮波比茶1 小时前
java日志框架
java
thefool1122661 小时前
随机链表的复制
java
jvmind_dev2 小时前
SWT 堆外内存泄漏排查实录:一次 PNG 保存泄漏一张图,一行 g_free 治好
java·后端
CodeStats2 小时前
《源纹天书》第三百四十六章至第三百五十章:边界的扩张、跨宇宙通信的尝试、其他宇宙的回应、新网络的形成、宇宙网络的创始者!
java·源纹天书
古法安卓3 小时前
Android-显示流程
android·java·android studio
l1t3 小时前
DeepSeek总结的DuckDB 如何更快地运行递归 CTE
java·开发语言·数据库·mysql·duckdb