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

相关推荐
唐青枫13 小时前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马14 小时前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户37215742613514 小时前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户37215742613515 小时前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454751 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
东坡白菜1 天前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
唐青枫1 天前
Java Tomcat 实战指南:从 Servlet 容器到 Spring Boot 部署
java
wsaaaqqq1 天前
roudan:自由选择实体、灵活操作数据、快速写入数据库的 Java 框架
java
plainGeekDev2 天前
null 判断 → Kotlin 可空类型
android·java·kotlin
糖拌西瓜皮2 天前
Java开发者视角:深入理解Node.js异步编程模型
java·后端·node.js