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