一、Spring 是什么?
1.1 定义
Spring 是一个开源的 Java 企业级应用开发框架,它提供了全面的基础设施支持,让开发者专注于业务逻辑。
Spring 框架的本质:
┌─────────────────────────────────────────┐
│ 简化 Java 企业级应用开发的框架 │
│ ├─ 轻量级(相对于 EJB) │
│ ├─ 非侵入式(POJO 编程) │
│ ├─ 控制反转(IoC) │
│ ├─ 面向切面编程(AOP) │
│ └─ 提供一站式解决方案 │
└─────────────────────────────────────────┘
1.2 Spring 的发展历程
| 版本 | 年份 | 重要特性 |
|---|---|---|
| Spring 1.x | 2004 | IoC 容器、AOP 支持 |
| Spring 2.x | 2006 | 基于注解的配置、AspectJ 集成 |
| Spring 3.x | 2009 | Java 配置、SpEL、REST 支持 |
| Spring 4.x | 2013 | Java 8 支持、WebSocket、条件注解 |
| Spring 5.x | 2017 | 响应式编程(WebFlux)、Kotlin 支持 |
| Spring 6.x | 2022 | Java 17 基线、原生编译支持 |
1.3 Spring 生态体系
Spring 生态:
┌──────────────────────────────────────────────────┐
│ Spring Framework(核心框架) │
│ ├─ Spring Core(IoC 容器) │
│ ├─ Spring AOP(面向切面编程) │
│ ├─ Spring Data Access(数据访问) │
│ └─ Spring Web(Web 应用) │
└──────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ Spring Boot(快速开发脚手架) │
│ ├─ 自动配置 │
│ ├─ 内嵌服务器 │
│ └─ 开箱即用 │
└──────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ Spring Cloud(微服务解决方案) │
│ ├─ 服务发现(Eureka) │
│ ├─ 配置中心(Config) │
│ ├─ 负载均衡(Ribbon) │
│ ├─ 断路器(Hystrix) │
│ └─ API 网关(Gateway) │
└──────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ 其他 Spring 项目 │
│ ├─ Spring Data(统一数据访问) │
│ ├─ Spring Security(安全框架) │
│ ├─ Spring Batch(批处理) │
│ └─ Spring Integration(企业集成) │
└──────────────────────────────────────────────────┘
二、Spring 的核心作用
2.1 解决的核心问题
问题1:对象创建和管理复杂
传统方式:
// 传统方式:手动创建对象,耦合度高
public class UserService {
// 手动创建依赖对象
private UserDao userDao = new UserDaoImpl();
public User findUser(Long id) {
return userDao.findById(id);
}
}
// 问题:
// 1. UserService 与 UserDaoImpl 紧耦合
// 2. 无法灵活切换实现(如:UserDaoMySqlImpl → UserDaoOracleImpl)
// 3. 难以进行单元测试(无法 Mock UserDao)
// 4. 对象生命周期管理困难
Spring 方式:
// Spring 方式:依赖注入,解耦
@Service
public class UserService {
// Spring 自动注入
@Autowired
private UserDao userDao;
public User findUser(Long id) {
return userDao.findById(id);
}
}
// 优势:
// 1. UserService 不关心 UserDao 的具体实现
// 2. 可以通过配置灵活切换实现
// 3. 易于测试(可以注入 Mock 对象)
// 4. Spring 管理对象的完整生命周期
问题2:横切关注点分散
传统方式:
// 传统方式:业务代码与系统关注点混杂
public class UserService {
public void createUser(User user) {
// 日志记录(横切关注点)
System.out.println("创建用户: " + user.getName());
// 事务管理(横切关注点)
Connection conn = dataSource.getConnection();
conn.setAutoCommit(false);
try {
// 业务逻辑
userDao.save(user);
// 提交事务
conn.commit();
// 日志记录
System.out.println("用户创建成功");
} catch (Exception e) {
// 回滚事务
conn.rollback();
// 日志记录
System.err.println("用户创建失败: " + e.getMessage());
}
}
}
// 问题:
// 1. 业务代码与日志、事务代码混在一起
// 2. 代码重复(每个方法都要写类似代码)
// 3. 维护困难(修改日志格式需要改很多地方)
Spring AOP 方式:
// Spring AOP 方式:关注点分离
@Service
public class UserService {
@Transactional // 声明式事务
@Logging // 自定义日志切面
public void createUser(User user) {
// 只关注业务逻辑
userDao.save(user);
}
}
// 优势:
// 1. 业务代码清晰,只包含业务逻辑
// 2. 横切关注点集中管理
// 3. 易于维护和修改
问题3:配置和集成复杂
传统方式:
// 传统方式:大量配置代码
public class AppConfig {
public void init() {
// 配置数据源
DataSource ds = new BasicDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/mydb");
ds.setUsername("root");
ds.setPassword("password");
// 配置事务管理器
DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
// 配置 JdbcTemplate
JdbcTemplate jdbc = new JdbcTemplate(ds);
// 配置各种 DAO
UserDao userDao = new UserDaoImpl(jdbc);
// 配置各种 Service
UserService userService = new UserService(userDao, tm);
// ... 大量重复代码
}
}
Spring 方式:
// Spring 方式:声明式配置
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/mydb")
.username("root")
.password("password")
.build();
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
或者使用 Spring Boot,连配置都不需要:
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
2.2 Spring 的六大核心价值
┌─────────────────────────────────────────────────┐
│ 1. 依赖注入(DI) │
│ └─ 解耦对象之间的依赖关系 │
├─────────────────────────────────────────────────┤
│ 2. 面向切面编程(AOP) │
│ └─ 分离横切关注点 │
├─────────────────────────────────────────────────┤
│ 3. 声明式事务管理 │
│ └─ 简化事务处理 │
├─────────────────────────────────────────────────┤
│ 4. 简化企业级应用开发 │
│ └─ 提供一站式解决方案 │
├─────────────────────────────────────────────────┤
│ 5. 方便集成 │
│ └─ 与各种框架无缝整合 │
├─────────────────────────────────────────────────┤
│ 6. 便于测试 │
│ └─ 支持单元测试和集成测试 │
└─────────────────────────────────────────────────┘
2.3 Spring vs 传统开发对比
| 维度 | 传统开发 | Spring |
|---|---|---|
| 对象创建 | 手动 new | IoC 容器管理 |
| 依赖管理 | 硬编码依赖 | 依赖注入 |
| 生命周期 | 手动管理 | 容器托管 |
| 事务管理 | 编程式(手动控制) | 声明式(@Transactional) |
| 日志记录 | 代码侵入 | AOP 切面 |
| 配置方式 | 繁琐的配置代码 | 注解 + 少量配置 |
| 测试 | 难以单元测试 | 易于测试(依赖注入) |
| 扩展性 | 耦合度高 | 松耦合,易扩展 |
三、Spring 核心原理
3.1 IoC(控制反转)原理
3.1.1 什么是 IoC?
控制反转(Inversion of Control):将对象的创建和依赖关系的管理从应用代码转移到 IoC 容器。
传统方式(正向控制):
Application
├─ 创建 UserService
├─ 创建 UserDao
└─ 将 UserDao 注入 UserService
IoC 方式(控制反转):
IoC Container
├─ 创建 UserDao
├─ 创建 UserService
└─ 自动注入依赖
↓
Application
└─ 从容器获取 UserService(已注入依赖)
核心思想:
“别调用我们,我们会调用你”(Hollywood Principle)
3.1.2 依赖注入(DI)的三种方式
1. 构造器注入(推荐)
@Service
public class UserService {
private final UserDao userDao;
private final EmailService emailService;
// Spring 自动调用构造器注入依赖
@Autowired // Spring 4.3+ 单构造器可省略
public UserService(UserDao userDao, EmailService emailService) {
this.userDao = userDao;
this.emailService = emailService;
}
}
// 优点:
// 1. 依赖对象不可变(final)
// 2. 确保依赖不为 null
// 3. 易于单元测试
2. Setter 注入
@Service
public class UserService {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
// 优点:
// 1. 可选依赖
// 2. 可以重新注入
// 缺点:
// 1. 依赖可变
// 2. 可能为 null
3. 字段注入(不推荐)
@Service
public class UserService {
@Autowired
private UserDao userDao;
}
// 优点:
// 1. 代码简洁
// 缺点:
// 1. 难以测试(无法注入 Mock 对象)
// 2. 违反封装性
// 3. 依赖不明确
3.1.3 Spring IoC 容器的实现原理
核心接口:
BeanFactory(根接口)
├─ ListableBeanFactory
├─ HierarchicalBeanFactory
└─ AutowireCapableBeanFactory
↓
ApplicationContext(高级容器)
├─ ClassPathXmlApplicationContext
├─ FileSystemXmlApplicationContext
└─ AnnotationConfigApplicationContext
容器启动流程:
// 简化的容器启动流程
public class SimplifiedApplicationContext {
// 1. 加载配置(扫描注解)
public void loadBeanDefinitions() {
// 扫描 @Component、@Service、@Repository、@Controller
// 解析 @Configuration、@Bean
// 生成 BeanDefinition(Bean 的元数据)
}
// 2. 注册 BeanDefinition
public void registerBeanDefinitions(BeanDefinition bd) {
// 存储到 beanDefinitionMap
beanDefinitionMap.put(bd.getBeanName(), bd);
}
// 3. 实例化 Bean
public Object createBean(BeanDefinition bd) {
// 3.1 实例化:反射创建对象
Object bean = bd.getBeanClass().newInstance();
// 3.2 属性注入:依赖注入
populateBean(bean, bd);
// 3.3 初始化:调用初始化方法
initializeBean(bean, bd);
return bean;
}
// 4. 依赖注入
public void populateBean(Object bean, BeanDefinition bd) {
// 查找需要注入的字段/方法
// 从容器中获取依赖 Bean
// 反射注入
}
// 5. 初始化 Bean
public Object initializeBean(Object bean, BeanDefinition bd) {
// 调用 @PostConstruct 方法
// 调用 InitializingBean.afterPropertiesSet()
// 调用自定义的 init-method
return bean;
}
}
Bean 的完整生命周期:
1. 实例化 Bean
├─ 反射调用构造器
└─ 创建 Bean 实例
↓
2. 属性注入
├─ 依赖查找
└─ 反射注入依赖
↓
3. Aware 接口回调
├─ BeanNameAware.setBeanName()
├─ BeanFactoryAware.setBeanFactory()
└─ ApplicationContextAware.setApplicationContext()
↓
4. BeanPostProcessor 前置处理
└─ postProcessBeforeInitialization()
↓
5. 初始化
├─ @PostConstruct 方法
├─ InitializingBean.afterPropertiesSet()
└─ 自定义 init-method
↓
6. BeanPostProcessor 后置处理
└─ postProcessAfterInitialization()
↓
7. Bean 可用
└─ 放入单例池(singletonObjects)
↓
8. 销毁 Bean
├─ @PreDestroy 方法
├─ DisposableBean.destroy()
└─ 自定义 destroy-method
核心数据结构:
// Spring 容器的核心数据结构(简化)
public class DefaultListableBeanFactory {
// 1. BeanDefinition 注册表
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
// 2. 单例池(一级缓存)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
// 3. 早期单例对象(三级缓存,解决循环依赖)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
// 4. 早期单例对象(二级缓存)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
}
3.1.4 循环依赖解决原理
问题:A 依赖 B,B 依赖 A,如何解决?
@Service
public class A {
@Autowired
private B b;
}
@Service
public class B {
@Autowired
private A a;
}
Spring 的三级缓存解决方案:
创建 A:
1. 实例化 A(未注入依赖)
└─ 放入三级缓存(singletonFactories)
↓
2. 注入 A 的依赖:需要 B
└─ 创建 B
↓
创建 B:
3. 实例化 B(未注入依赖)
└─ 放入三级缓存
↓
4. 注入 B 的依赖:需要 A
├─ 从三级缓存获取 A 的早期引用
├─ 移到二级缓存(earlySingletonObjects)
└─ 注入到 B
↓
5. B 初始化完成
└─ 放入一级缓存(singletonObjects)
↓
6. 将完整的 B 注入到 A
↓
7. A 初始化完成
└─ 放入一级缓存
三级缓存的作用:
| 缓存 | 名称 | 存储内容 | 作用 |
|---|---|---|---|
| 一级 | singletonObjects | 完整的单例 Bean | 存储最终的 Bean |
| 二级 | earlySingletonObjects | 早期的 Bean(未初始化) | AOP 代理对象缓存 |
| 三级 | singletonFactories | Bean 工厂 | 解决循环依赖 |
3.2 AOP(面向切面编程)原理
3.2.1 什么是 AOP?
AOP(Aspect-Oriented Programming):将横切关注点(cross-cutting concerns)从业务逻辑中分离出来。
传统 OOP:
UserService
├─ createUser()
│ ├─ 日志记录 ←┐
│ ├─ 事务管理 ←┼─ 横切关注点(重复代码)
│ ├─ 权限检查 ←┤
│ └─ 业务逻辑 │
├─ updateUser() │
│ ├─ 日志记录 ←┤
│ ├─ 事务管理 ←┤
│ └─ ... ─┘
AOP 方式:
UserService
├─ createUser() ← 只包含业务逻辑
└─ updateUser() ← 只包含业务逻辑
横切关注点(统一管理):
├─ LoggingAspect(日志切面)
├─ TransactionAspect(事务切面)
└─ SecurityAspect(权限切面)
3.2.2 AOP 核心概念
| 概念 | 说明 | 示例 |
|---|---|---|
| Aspect(切面) | 横切关注点的模块化 | 日志切面、事务切面 |
| Join Point(连接点) | 可以插入切面的点 | 方法执行、异常抛出 |
| Pointcut(切点) | 匹配连接点的表达式 | execution(* com.example..*.*(..)) |
| Advice(通知) | 在切点执行的动作 | Before、After、Around |
| Target(目标对象) | 被代理的对象 | UserService |
| Proxy(代理对象) | AOP 创建的代理 | UserService$$Proxy |
| Weaving(织入) | 将切面应用到目标对象 | 运行时织入(Spring) |
完整示例:
// 切面类
@Aspect
@Component
public class LoggingAspect {
// 切点:匹配所有 Service 方法
@Pointcut("execution(* com.example.service..*.*(..))")
public void serviceMethods() {}
// 前置通知
@Before("serviceMethods()")
public void logBefore(JoinPoint joinPoint) {
System.out.println("方法执行前: " + joinPoint.getSignature());
}
// 后置通知
@After("serviceMethods()")
public void logAfter(JoinPoint joinPoint) {
System.out.println("方法执行后: " + joinPoint.getSignature());
}
// 环绕通知(最强大)
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
// 执行目标方法
Object result = pjp.proceed();
long end = System.currentTimeMillis();
System.out.println("方法耗时: " + (end - start) + "ms");
return result;
}
// 返回通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("方法返回值: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
System.out.println("方法抛出异常: " + ex.getMessage());
}
}
3.2.3 Spring AOP 实现原理
Spring AOP 基于动态代理实现:
1. JDK 动态代理(基于接口)
// 目标对象实现了接口
public interface UserService {
void createUser(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void createUser(User user) {
System.out.println("创建用户: " + user.getName());
}
}
// Spring 使用 JDK 动态代理
UserService proxy = (UserService) Proxy.newProxyInstance(
classLoader,
new Class[]{UserService.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
// 前置通知
System.out.println("Before: " + method.getName());
// 执行目标方法
Object result = method.invoke(target, args);
// 后置通知
System.out.println("After: " + method.getName());
return result;
}
}
);
2. CGLIB 动态代理(基于子类)
// 目标对象没有实现接口
@Service
public class UserService {
public void createUser(User user) {
System.out.println("创建用户: " + user.getName());
}
}
// Spring 使用 CGLIB 创建子类代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
// 前置通知
System.out.println("Before: " + method.getName());
// 执行目标方法(调用父类方法)
Object result = proxy.invokeSuper(obj, args);
// 后置通知
System.out.println("After: " + method.getName());
return result;
}
});
UserService proxy = (UserService) enhancer.create();
JDK 代理 vs CGLIB 代理:
| 维度 | JDK 动态代理 | CGLIB 代理 |
|---|---|---|
| 实现方式 | 基于接口(Proxy.newProxyInstance) | 基于继承(生成子类) |
| 要求 | 目标类必须实现接口 | 目标类不能是 final |
| 性能 | 略低 | 略高 |
| Spring 选择 | 有接口优先使用 | 无接口时使用 |
AOP 代理创建流程:
1. Bean 创建阶段
├─ 实例化目标对象
└─ 属性注入
↓
2. BeanPostProcessor 后置处理
├─ AbstractAutoProxyCreator.postProcessAfterInitialization()
├─ 查找匹配的 Advisor(切面)
└─ 如果有匹配的切面 → 创建代理
↓
3. 创建代理对象
├─ 判断:目标类是否实现接口?
├─ 是 → JDK 动态代理
└─ 否 → CGLIB 代理
↓
4. 返回代理对象
└─ 放入容器(代替原始 Bean)
方法调用流程:
用户调用
↓
代理对象.method()
↓
InvocationHandler.invoke() / MethodInterceptor.intercept()
├─ 获取该方法的拦截器链(Advisor Chain)
├─ 依次执行拦截器
│ ├─ @Before 通知
│ ├─ @Around 通知(前)
│ ├─ 目标方法执行 ← method.invoke(target, args)
│ ├─ @Around 通知(后)
│ ├─ @After 通知
│ └─ @AfterReturning / @AfterThrowing
└─ 返回结果
3.3 Spring 事务管理原理
3.3.1 声明式事务
@Service
public class UserService {
@Transactional // 声明式事务
public void createUser(User user) {
userDao.save(user);
accountDao.createAccount(user.getId());
// 如果抛出异常,自动回滚
}
}
等价于:
// 编程式事务(传统方式)
public void createUser(User user) {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
userDao.save(user);
accountDao.createAccount(user.getId());
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
}
3.3.2 事务实现原理
基于 AOP 实现:
@Transactional 方法
↓
TransactionInterceptor(事务拦截器)
↓
1. 开启事务
└─ transactionManager.getTransaction()
↓
2. 执行目标方法
└─ method.proceed()
↓
3. 提交或回滚
├─ 成功 → transactionManager.commit()
└─ 异常 → transactionManager.rollback()
事务管理器体系:
PlatformTransactionManager(顶层接口)
├─ DataSourceTransactionManager(JDBC)
├─ HibernateTransactionManager(Hibernate)
├─ JpaTransactionManager(JPA)
└─ JtaTransactionManager(分布式事务)
事务传播行为:
| 传播行为 | 说明 | 示例场景 |
|---|---|---|
| REQUIRED(默认) | 有事务加入,无事务新建 | 最常用 |
| REQUIRES_NEW | 总是新建事务,挂起当前事务 | 记录日志(不受外层事务影响) |
| NESTED | 嵌套事务(保存点) | 部分回滚 |
| SUPPORTS | 有事务加入,无事务以非事务执行 | 查询方法 |
| NOT_SUPPORTED | 以非事务执行,挂起当前事务 | 批处理 |
| NEVER | 以非事务执行,有事务抛异常 | 强制非事务 |
| MANDATORY | 必须在事务中执行,无事务抛异常 | 强制事务 |
示例:
@Service
public class OrderService {
@Autowired
private LogService logService;
@Transactional
public void createOrder(Order order) {
orderDao.save(order); // 主业务
// 记录日志(独立事务,不受主事务影响)
logService.log("订单创建: " + order.getId());
// 如果后续出错,订单回滚,但日志已提交
}
}
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String message) {
logDao.save(message);
// 独立提交,不受外层事务影响
}
}
四、Spring 核心模块
4.1 模块架构
Spring Framework
├─ Core Container(核心容器)
│ ├─ spring-core(核心工具类)
│ ├─ spring-beans(Bean 管理)
│ ├─ spring-context(应用上下文)
│ └─ spring-expression(SpEL 表达式)
│
├─ AOP
│ ├─ spring-aop(AOP 支持)
│ └─ spring-aspects(AspectJ 集成)
│
├─ Data Access/Integration(数据访问)
│ ├─ spring-jdbc(JDBC 支持)
│ ├─ spring-tx(事务管理)
│ ├─ spring-orm(ORM 集成)
│ └─ spring-jms(消息队列)
│
├─ Web
│ ├─ spring-web(Web 基础)
│ ├─ spring-webmvc(Spring MVC)
│ └─ spring-webflux(响应式 Web)
│
└─ Test
└─ spring-test(测试支持)
4.2 核心容器详解
4.2.1 spring-core
核心工具类:
// 1. 资源访问
Resource resource = new ClassPathResource("config.properties");
InputStream is = resource.getInputStream();
// 2. 类型转换
ConversionService conversionService = new DefaultConversionService();
Integer num = conversionService.convert("123", Integer.class);
// 3. 环境抽象
Environment env = applicationContext.getEnvironment();
String profile = env.getActiveProfiles()[0];
4.2.2 spring-beans
Bean 定义和管理:
// Bean 定义
BeanDefinition bd = BeanDefinitionBuilder
.rootBeanDefinition(UserService.class)
.setScope(BeanDefinition.SCOPE_SINGLETON)
.addPropertyValue("userDao", userDao)
.getBeanDefinition();
// Bean 工厂
BeanFactory beanFactory = new XmlBeanFactory(resource);
UserService userService = beanFactory.getBean(UserService.class);
4.2.3 spring-context
应用上下文:
// 注解配置
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// XML 配置
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// Web 环境
WebApplicationContext webContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
4.3 数据访问模块
4.3.1 spring-jdbc
JdbcTemplate 简化 JDBC 操作:
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
}
@Override
public List<User> findAll() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
}
@Override
public int save(User user) {
String sql = "INSERT INTO users(name, email) VALUES(?, ?)";
return jdbcTemplate.update(sql, user.getName(), user.getEmail());
}
}
优势:
- 自动资源管理(Connection、Statement、ResultSet)
- 异常转换(SQLException → DataAccessException)
- 简化代码
4.3.2 spring-tx
事务管理:
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
@Service
public class UserService {
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 30,
rollbackFor = Exception.class
)
public void createUser(User user) {
userDao.save(user);
}
}
4.4 Web 模块
4.4.1 Spring MVC
核心组件:
请求流程:
Client Request
↓
DispatcherServlet(前端控制器)
↓
HandlerMapping(处理器映射)
└─ 找到对应的 Controller
↓
HandlerAdapter(处理器适配器)
└─ 执行 Controller 方法
↓
Controller(控制器)
└─ 返回 ModelAndView
↓
ViewResolver(视图解析器)
└─ 解析视图名称
↓
View(视图)
└─ 渲染响应
↓
Client Response
示例:
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.update(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
}
五、Spring 重要的类和接口
5.1 核心容器类
5.1.1 BeanFactory 体系
// 1. BeanFactory - 根接口
public interface BeanFactory {
Object getBean(String name);
<T> T getBean(String name, Class<T> requiredType);
<T> T getBean(Class<T> requiredType);
boolean containsBean(String name);
boolean isSingleton(String name);
boolean isPrototype(String name);
}
// 2. ListableBeanFactory - 可列举 Bean
public interface ListableBeanFactory extends BeanFactory {
String[] getBeanDefinitionNames();
<T> Map<String, T> getBeansOfType(Class<T> type);
String[] getBeanNamesForType(Class<?> type);
}
// 3. ConfigurableBeanFactory - 可配置的 Bean 工厂
public interface ConfigurableBeanFactory extends BeanFactory {
void setBeanClassLoader(ClassLoader beanClassLoader);
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
void destroySingletons();
}
// 4. DefaultListableBeanFactory - 默认实现
public class DefaultListableBeanFactory
extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {
// Bean 定义注册表
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 单例池
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
}
5.1.2 ApplicationContext 体系
// 1. ApplicationContext - 应用上下文
public interface ApplicationContext extends EnvironmentCapable,
ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
String getId();
String getDisplayName();
long getStartupDate();
ApplicationContext getParent();
AutowireCapableBeanFactory getAutowireCapableBeanFactory();
}
// 2. ConfigurableApplicationContext - 可配置的应用上下文
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
void setEnvironment(ConfigurableEnvironment environment);
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
void refresh() throws BeansException;
void close();
}
// 3. 常用实现类
public class AnnotationConfigApplicationContext
extends GenericApplicationContext
implements AnnotationConfigRegistry {
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
}
public class ClassPathXmlApplicationContext
extends AbstractXmlApplicationContext {
public ClassPathXmlApplicationContext(String configLocation) {
this(new String[]{configLocation}, true, null);
}
}
5.2 Bean 生命周期相关接口
// 1. BeanPostProcessor - Bean 后置处理器
public interface BeanPostProcessor {
// Bean 初始化前调用
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
// Bean 初始化后调用
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
// 2. InitializingBean - 初始化 Bean
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
// 3. DisposableBean - 销毁 Bean
public interface DisposableBean {
void destroy() throws Exception;
}
// 4. Aware 接口系列
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory);
}
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext);
}
使用示例:
@Component
public class UserService implements BeanNameAware, ApplicationContextAware,
InitializingBean, DisposableBean {
private String beanName;
private ApplicationContext applicationContext;
// 1. BeanNameAware 回调
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("BeanNameAware: " + name);
}
// 2. ApplicationContextAware 回调
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
System.out.println("ApplicationContextAware");
}
// 3. 初始化方法
@PostConstruct
public void init() {
System.out.println("@PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean.afterPropertiesSet()");
}
// 4. 销毁方法
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy");
}
@Override
public void destroy() {
System.out.println("DisposableBean.destroy()");
}
}
5.3 AOP 相关类
// 1. Advisor - 通知器(Pointcut + Advice)
public interface Advisor {
Advice getAdvice();
}
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
// 2. Pointcut - 切点
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
// 3. Advice - 通知
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, @Nullable Object target);
}
public interface AfterReturningAdvice extends AfterAdvice {
void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target);
}
// 4. JoinPoint - 连接点
public interface JoinPoint {
Object[] getArgs();
Signature getSignature();
Object getTarget();
Object getThis();
}
public interface ProceedingJoinPoint extends JoinPoint {
Object proceed() throws Throwable;
Object proceed(Object[] args) throws Throwable;
}
5.4 事务相关类
// 1. PlatformTransactionManager - 事务管理器
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition);
void commit(TransactionStatus status);
void rollback(TransactionStatus status);
}
// 2. TransactionDefinition - 事务定义
public interface TransactionDefinition {
int getPropagationBehavior(); // 传播行为
int getIsolationLevel(); // 隔离级别
int getTimeout(); // 超时时间
boolean isReadOnly(); // 只读标识
}
// 3. TransactionStatus - 事务状态
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
boolean isCompleted();
}
// 4. @Transactional 注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
}
5.5 Web MVC 相关类
// 1. DispatcherServlet - 前端控制器
public class DispatcherServlet extends FrameworkServlet {
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) {
doDispatch(request, response);
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
// 1. 获取 Handler
HandlerExecutionChain mappedHandler = getHandler(request);
// 2. 获取 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 执行 Handler
ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());
// 4. 处理视图
processDispatchResult(request, response, mappedHandler, mv, dispatchException);
}
}
// 2. HandlerMapping - 处理器映射
public interface HandlerMapping {
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
// 3. HandlerAdapter - 处理器适配器
public interface HandlerAdapter {
boolean supports(Object handler);
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler);
}
// 4. ViewResolver - 视图解析器
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
5.6 常用注解
// 1. 组件注解
@Component // 通用组件
@Service // 业务层组件
@Repository // 数据访问层组件
@Controller // 控制层组件
@RestController // RESTful 控制器
// 2. 配置注解
@Configuration // 配置类
@Bean // Bean 定义
@ComponentScan // 组件扫描
@Import // 导入配置
// 3. 依赖注入注解
@Autowired // 自动装配
@Qualifier // 指定 Bean 名称
@Resource // JSR-250 注入
@Value // 注入值
// 4. 作用域注解
@Scope // Bean 作用域
@Lazy // 延迟初始化
// 5. AOP 注解
@Aspect // 切面
@Pointcut // 切点
@Before // 前置通知
@After // 后置通知
@Around // 环绕通知
@AfterReturning // 返回通知
@AfterThrowing // 异常通知
// 6. 事务注解
@Transactional // 声明式事务
@EnableTransactionManagement // 启用事务管理
// 7. Web MVC 注解
@RequestMapping // 请求映射
@GetMapping // GET 请求
@PostMapping // POST 请求
@PutMapping // PUT 请求
@DeleteMapping // DELETE 请求
@PathVariable // 路径变量
@RequestParam // 请求参数
@RequestBody // 请求体
@ResponseBody // 响应体
六、Spring 使用指南
6.1 快速开始
6.1.1 Maven 依赖
<dependencies>
<!-- Spring Context(包含 core、beans、context、expression) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.30</version>
</dependency>
<!-- Spring AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.30</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.30</version>
</dependency>
<!-- Spring Web MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.30</version>
</dependency>
</dependencies>
6.1.2 基于注解的配置(推荐)
// 1. 配置类
@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class AppConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
// 2. 启动应用
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);
userService.createUser(new User("张三", "zhangsan@example.com"));
}
}
6.1.3 基于 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:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 启用注解扫描 -->
<context:component-scan base-package="com.example"/>
<!-- 启用 AOP -->
<aop:aspectj-autoproxy/>
<!-- 数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<!-- JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
// 启动应用
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean(UserService.class);
userService.createUser(new User("张三", "zhangsan@example.com"));
}
}
6.2 完整示例
6.2.1 实体类
public class User {
private Long id;
private String name;
private String email;
private Date createdAt;
// 构造器、Getter、Setter
}
6.2.2 DAO 层
public interface UserDao {
int save(User user);
User findById(Long id);
List<User> findAll();
int update(User user);
int delete(Long id);
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int save(User user) {
String sql = "INSERT INTO users(name, email, created_at) VALUES(?, ?, ?)";
return jdbcTemplate.update(sql, user.getName(), user.getEmail(), new Date());
}
@Override
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql,
new BeanPropertyRowMapper<>(User.class), id);
}
@Override
public List<User> findAll() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql,
new BeanPropertyRowMapper<>(User.class));
}
@Override
public int update(User user) {
String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
return jdbcTemplate.update(sql,
user.getName(), user.getEmail(), user.getId());
}
@Override
public int delete(Long id) {
String sql = "DELETE FROM users WHERE id = ?";
return jdbcTemplate.update(sql, id);
}
}
6.2.3 Service 层
public interface UserService {
User createUser(User user);
User findUser(Long id);
List<User> findAllUsers();
User updateUser(User user);
void deleteUser(Long id);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Transactional
@Override
public User createUser(User user) {
userDao.save(user);
return user;
}
@Override
public User findUser(Long id) {
return userDao.findById(id);
}
@Override
public List<User> findAllUsers() {
return userDao.findAll();
}
@Transactional
@Override
public User updateUser(User user) {
userDao.update(user);
return user;
}
@Transactional
@Override
public void deleteUser(Long id) {
userDao.delete(id);
}
}
6.2.4 AOP 日志切面
@Aspect
@Component
@Slf4j
public class LoggingAspect {
@Pointcut("execution(* com.example.service..*.*(..))")
public void serviceLayer() {}
@Around("serviceLayer()")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
String className = pjp.getTarget().getClass().getSimpleName();
String methodName = pjp.getSignature().getName();
Object[] args = pjp.getArgs();
log.info("{}. {} 开始执行,参数:{}", className, methodName, Arrays.toString(args));
long start = System.currentTimeMillis();
Object result = null;
try {
result = pjp.proceed();
long end = System.currentTimeMillis();
log.info("{}.{} 执行成功,耗时:{}ms,返回值:{}",
className, methodName, (end - start), result);
return result;
} catch (Exception e) {
log.error("{}.{} 执行失败:{}", className, methodName, e.getMessage());
throw e;
}
}
}
6.2.5 Controller 层(Spring MVC)
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User created = userService.createUser(user);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findUser(id);
return ResponseEntity.ok(user);
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.findAllUsers();
return ResponseEntity.ok(users);
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
User updated = userService.updateUser(user);
return ResponseEntity.ok(updated);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
七、Spring Boot 简介
7.1 Spring Boot 的作用
Spring Boot 简化了 Spring 应用的开发:
| 传统 Spring | Spring Boot |
|---|---|
| 大量 XML 配置 | 自动配置 |
| 依赖版本管理复杂 | starter 依赖 |
| 部署需要外部容器 | 内嵌服务器 |
| 配置分散 | 统一配置(application.yml) |
7.2 Spring Boot 快速开始
<!-- pom.xml -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
</parent>
<dependencies>
<!-- Web 应用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
</dependencies>
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
jpa:
hibernate:
ddl-auto: update
show-sql: true
// 启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 实体类
@Entity
@Table(name = "users")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
// Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name);
}
// Service
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User save(User user) {
return userRepository.save(user);
}
}
// Controller
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public User create(@RequestBody User user) {
return userService.save(user);
}
}
7.3 Spring Boot 核心特性
1. 自动配置(Auto-Configuration)
└─ 根据 classpath 自动配置 Bean
2. Starter 依赖
├─ spring-boot-starter-web(Web 应用)
├─ spring-boot-starter-data-jpa(JPA)
├─ spring-boot-starter-security(安全)
└─ spring-boot-starter-test(测试)
3. 内嵌服务器
├─ Tomcat(默认)
├─ Jetty
└─ Undertow
4. 生产就绪特性
├─ Actuator(监控端点)
├─ Metrics(指标收集)
└─ Health Check(健康检查)
5. 外部化配置
├─ application.properties
├─ application.yml
├─ 环境变量
└─ 命令行参数
八、Spring 最佳实践
8.1 依赖注入最佳实践
// ✅ 推荐:构造器注入
@Service
public class UserService {
private final UserDao userDao;
private final EmailService emailService;
// Spring 4.3+ 单构造器可省略 @Autowired
public UserService(UserDao userDao, EmailService emailService) {
this.userDao = userDao;
this.emailService = emailService;
}
}
// ❌ 不推荐:字段注入
@Service
public class UserService {
@Autowired
private UserDao userDao; // 难以测试
}
8.2 Bean 作用域使用
// 1. Singleton(默认)- 单例
@Service
@Scope("singleton")
public class UserService {
// 线程不安全:不要有状态字段
}
// 2. Prototype - 每次获取创建新实例
@Service
@Scope("prototype")
public class TaskProcessor {
// 有状态 Bean 使用 prototype
}
// 3. Request - Web 请求范围
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserContext {
private User currentUser;
}
// 4. Session - Web 会话范围
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ShoppingCart {
private List<Item> items;
}
8.3 事务管理最佳实践
// ✅ 推荐做法
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private InventoryService inventoryService;
// 1. 事务加在 Service 层
@Transactional
public void createOrder(Order order) {
orderDao.save(order);
inventoryService.decreaseStock(order.getProductId(), order.getQuantity());
}
// 2. 只读事务优化查询
@Transactional(readOnly = true)
public Order findOrder(Long id) {
return orderDao.findById(id);
}
// 3. 指定回滚异常
@Transactional(rollbackFor = Exception.class)
public void processOrder(Order order) throws Exception {
// 业务逻辑
}
}
// ❌ 常见错误
@Service
public class UserService {
@Autowired
private UserDao userDao;
// 错误1:同类方法调用,事务失效
public void createUser(User user) {
saveUser(user); // 直接调用,不走代理,事务失效
}
@Transactional
public void saveUser(User user) {
userDao.save(user);
}
// 错误2:非 public 方法,事务失效
@Transactional
protected void updateUser(User user) { // 非 public
userDao.update(user);
}
// 错误3:捕获异常不抛出,事务不回滚
@Transactional
public void deleteUser(Long id) {
try {
userDao.delete(id);
} catch (Exception e) {
e.printStackTrace(); // 吞掉异常,事务不回滚
}
}
}
8.4 配置管理最佳实践
// 1. 使用 @ConfigurationProperties(类型安全)
@ConfigurationProperties(prefix = "app")
@Component
@Data
public class AppProperties {
private String name;
private String version;
private Database database;
@Data
public static class Database {
private String url;
private String username;
private String password;
}
}
// application.yml
app:
name: MyApp
version: 1.0.0
database:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
// 2. 使用 @Value(简单值)
@Component
public class EmailService {
@Value("${email.smtp.host}")
private String smtpHost;
@Value("${email.smtp.port:587}") // 默认值
private int smtpPort;
}
// 3. 多环境配置
// application-dev.yml
// application-test.yml
// application-prod.yml
// 激活配置:
// spring.profiles.active=prod
8.5 异常处理最佳实践
// 1. 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse("NOT_FOUND", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneral(Exception ex) {
ErrorResponse error = new ErrorResponse("INTERNAL_ERROR", "系统错误");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
// 2. 自定义业务异常
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
// 3. Service 层抛出业务异常
@Service
public class UserService {
public User findUser(Long id) {
return userDao.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("用户不存在: " + id));
}
}
8.6 性能优化建议
// 1. 延迟加载
@Configuration
public class AppConfig {
@Bean
@Lazy // 延迟初始化
public HeavyService heavyService() {
return new HeavyService();
}
}
// 2. 异步处理
@Service
public class EmailService {
@Async // 异步执行
public void sendEmail(String to, String subject, String content) {
// 发送邮件
}
}
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.initialize();
return executor;
}
}
// 3. 缓存
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User findUser(Long id) {
return userDao.findById(id);
}
@CacheEvict(value = "users", key = "#user.id")
public User updateUser(User user) {
return userDao.update(user);
}
}
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("users");
}
}
168万+

被折叠的 条评论
为什么被折叠?



