以下是一个完整的 纯 XML 配置开发示例,涵盖 DAO、Service、Controller 层,通过 Spring XML 配置实现依赖注入和事务管理,无需任何注解。
1. 项目结构
src/main/java
├── com.example.dao
│ └── UserDao.java # DAO 接口
│ └── impl
│ └── UserDaoImpl.java # DAO 实现类
├── com.example.service
│ ├── UserService.java # Service 接口
│ └── impl
│ └── UserServiceImpl.java # Service 实现类
└── com.example.controller
└── UserController.java # Controller 类
resources
├── applicationContext.xml # Spring 主配置文件
└── db.properties # 数据库配置文件
2. XML 配置 (applicationContext.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"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1. 启用组件扫描(DAO、Service、Controller) -->
<context:component-scan base-package="com.example"/>
<!-- 2. 数据源配置(通过 properties 文件注入) -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 3. JdbcTemplate 配置(用于 DAO 层) -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 4. 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 5. 启用注解驱动的事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 6. Service 层事务配置(AOP 方式) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(* com.example.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
</beans>
3. DAO 层 (UserDao.java
和 UserDaoImpl.java
)
接口 (UserDao.java
)
package com.example.dao;
import com.example.model.User;
public interface UserDao {
User findById(int id);
}
实现类 (UserDaoImpl.java
)
package com.example.dao.impl;
import com.example.dao.UserDao;
import com.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public User findById(int id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) ->
new User(rs.getInt("id"), rs.getString("name"))
);
}
}
4. Service 层 (UserService.java
和 UserServiceImpl.java
)
接口 (UserService.java
)
package com.example.service;
import com.example.model.User;
public interface UserService {
User getUserById(int id);
}
实现类 (UserServiceImpl.java
)
package com.example.service.impl;
import com.example.dao.UserDao;
import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public User getUserById(int id) {
return userDao.findById(id);
}
}
5. Controller 层 (UserController.java
)
package com.example.controller;
import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public User getUser(@PathVariable int id) {
return userService.getUserById(id);
}
}
6. 模型类 (User.java
)
package com.example.model;
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
// Getter 和 Setter 省略
}
7. 数据库配置 (db.properties
)
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.username=root
jdbc.password=secret
8. 启动应用
主类 (Application.java
)
package com.example;
import com.example.config.AppConfig;
import com.example.controller.UserController;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Application {
public static void main(String[] args) {
// 初始化 Spring 上下文
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取 Controller 并测试
UserController userController = context.getBean(UserController.class);
User user = userController.getUser(1);
System.out.println("User: " + user.getName());
// 关闭上下文
context.close();
}
}
9. Spring MVC 配置(web.xml
)
<web-app>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
10. 依赖(Maven pom.xml
)
<dependencies>
<!-- Spring 核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.20</version>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.20</version>
</dependency>
<!-- JSON 序列化 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
</dependencies>
关键点说明
-
纯 XML 配置
- 所有 Bean 定义、依赖注入、事务管理均通过 XML 实现,无需任何注解。
- 使用
<context:component-scan>
实现组件扫描,替代@ComponentScan
。
-
事务管理
- 通过
<tx:advice>
和<aop:config>
配置事务属性(传播行为、隔离级别)。 - 在 Service 方法上无需添加
@Transactional
。
- 通过
-
数据源和连接池
- 使用 HikariCP 连接池,配置通过
db.properties
文件注入。
- 使用 HikariCP 连接池,配置通过
-
Controller 层
- 使用
@RestController
和@GetMapping
注解(此处假设已通过 XML 配置 Spring MVC)。
- 使用
常见问题排查
-
Bean 未找到
- 检查
<context:component-scan>
的包路径是否正确。 - 确保类名与 XML 中定义的 Bean ID 一致(如
userService
)。
- 检查
-
事务不生效
- 检查
<tx:advice>
是否配置了正确的事务属性。 - 确保
<aop:config>
正确指向 Service 层方法。
- 检查
-
数据库连接失败
- 检查
db.properties
中的 URL、用户名和密码。 - 确保数据库驱动已添加到依赖(如 MySQL 的
mysql-connector-java
)。
- 检查
通过这种方式,可以完全基于 XML 配置实现 Spring 的依赖注入和事务管理,适合需要严格分离配置与代码的遗留项目。