Spring 全家桶从入门到精通
一份系统的 Spring 生态学习指南,覆盖 Spring 框架核心到微服务全栈。
1. Spring 生态概述
1.1 Spring 全家桶图谱
Spring 生态全景:
┌──────────────────────────────┐
│ Spring Boot │ ← 快速构建的基石
│ 自动配置 · 起步依赖 · Actuator │
└──────────────┬───────────────┘
│
┌───────────┬───────────────┼───────────────┬───────────┐
│ │ │ │ │
┌────▼────┐ ┌───▼────┐ ┌──────▼──────┐ ┌─────▼────┐ ┌───▼────┐
│ Spring │ │Spring │ │ Spring │ │ Spring │ │Spring │
│ Framework│ │ MVC │ │ Data │ │ Security │ │ Cloud │
│ IoC/AOP │ │ Web MVC│ │ JPA/Redis │ │ 认证授权 │ │ 微服务 │
└─────────┘ └────────┘ └────────────┘ └──────────┘ └────────┘
1.2 各模块定位
| 模块 |
定位 |
一句话说明 |
| Spring Framework |
基础核心 |
IoC 容器 + AOP,所有模块的基石 |
| Spring Boot |
快速开发 |
自动配置 + 起步依赖,简化 Spring 项目搭建 |
| Spring MVC |
Web 框架 |
基于 Servlet 的 MVC 架构,处理 HTTP 请求 |
| Spring Data |
数据访问 |
统一的数据访问抽象,支持 JPA、Redis、MongoDB 等 |
| Spring Security |
安全框架 |
认证 + 授权,保护应用安全 |
| Spring Cloud |
微服务 |
服务发现、配置中心、网关等微服务治理组件 |
1.3 版本命名
Spring Boot 版本号:2.7.18
│ │ │
│ │ └── 补丁版本(修订 bug)
│ └───── 次要版本(新功能、不兼容变更)
└─────── 主要版本(重大变更)
Spring Framework 版本:6.0.x → Spring Boot 3.x 配套
5.3.x → Spring Boot 2.x 配套
2. Spring Framework 核心
2.1 两大核心机制
| 机制 |
说明 |
| IoC(控制反转) |
对象的创建权从程序员反转给 Spring 容器 |
| AOP(面向切面编程) |
在不修改源码的前提下增强方法(日志、事务等) |
2.2 模块结构
spring-core IoC 容器基础
spring-beans Bean 工厂
spring-context 应用上下文(ApplicationContext)
spring-aop AOP 支持
spring-jdbc JDBC 抽象层
spring-tx 事务管理
spring-web Web 基础支持
spring-webmvc Spring MVC
spring-test 单元测试支持
2.3 核心 Jar 依赖
<!-- Maven:Spring Framework 核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.22</version>
</dependency>
<!-- 实际开发中直接用 Spring Boot 起步依赖,不直接引 -->
3. Spring IoC 容器
3.1 什么是 IoC?
IoC(Inversion of Control,控制反转):将对象的创建、组装、管理权交给 Spring 容器,程序员只关心业务逻辑。
传统方式:
public class UserService {
private UserDao userDao = new UserDao(); // 自己 new,强耦合
}
IoC 方式:
public class UserService {
private UserDao userDao; // 等待容器注入
}
比喻:
- ❌ 传统:想吃饭 → 自己买菜、洗菜、做饭、洗碗
- ✅ IoC:想吃饭 → 去餐厅,厨师(容器)做好端给你
3.2 容器接口
┌─────────────────────────────────────┐
│ BeanFactory │ ← 最底层容器(延迟加载)
└────────────┬────────────────────────┘
│
┌────────────▼────────────────────────┐
│ ApplicationContext │ ← 企业级容器(预加载 + 扩展功能)
│ ├─ ClassPathXmlApplicationContext │ 从 classpath 加载 XML
│ ├─ AnnotationConfigApplicationContext │ 从配置类加载
│ └─ GenericApplicationContext │ 编程式注册
└─────────────────────────────────────┘
// 从配置类加载容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
// 获取 Bean
UserService userService = ctx.getBean(UserService.class);
3.3 声明 Bean 的方式
方式一:注解 + 组件扫描(最常用)
@Component // 通用组件
@Service // 业务层
@Repository // 数据访问层
@Controller // 控制层
@RestController // REST 控制层
@SpringBootApplication // 自动启用组件扫描
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
方式二:@Configuration + @Bean
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost:5432/demo");
ds.setUsername("postgres");
ds.setPassword("123456");
return ds;
}
@Bean
public UserService userService() {
return new UserService(dataSource()); // 方法参数自动注入
}
}
方式三:XML 配置(传统方式,逐渐淘汰)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.example.service.UserService">
<constructor-arg ref="userDao" />
</bean>
<bean id="userDao" class="com.example.dao.UserDao" />
</beans>
3.4 Bean 作用域
| 作用域 |
说明 |
singleton(默认) |
整个容器只有一个实例,所有请求共享 |
prototype |
每次获取都创建新实例 |
request |
一次 HTTP 请求共享一个实例(Web 环境) |
session |
一次 HTTP 会话共享一个实例(Web 环境) |
application |
整个 ServletContext 共享一个实例 |
@Component
@Scope("prototype")
public class TaskProcessor { }
3.5 条件装配
@Configuration
public class DataSourceConfig {
@Bean
@ConditionalOnProperty(name = "app.datasource.type", havingValue = "h2")
public DataSource h2DataSource() {
return new HikariDataSource();
}
@Bean
@ConditionalOnMissingBean(DataSource.class)
public DataSource defaultDataSource() {
return new HikariDataSource();
}
}
4. Spring DI 依赖注入
4.1 三种注入方式
方式一:构造器注入(推荐 ✅)
@Service
public class UserService {
private final UserDao userDao;
private final EmailService emailService;
@Autowired // Spring 4.3+ 可省略(单构造器时)
public UserService(UserDao userDao, EmailService emailService) {
this.userDao = userDao;
this.emailService = emailService;
}
}
优点:
- 注入后不可变(
final 关键字)
- 依赖明确,创建对象时必须提供全部依赖
- 便于测试(直接 new 传 Mock 对象即可)
- 避免循环依赖(构造器注入的循环依赖会在启动时报错)
方式二:Setter 注入
@Service
public class UserService {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
适用场景:可选依赖,或需要在注入后做初始化操作。
方式三:字段注入(不推荐 ❌)
@Service
public class UserService {
@Autowired
private UserDao userDao; // 直接在字段上注入
}
缺点:
- 无法用
final 修饰
- 无法直接 new 出来测试(必须依赖 Spring 容器启动)
- 隐藏了依赖关系,代码可读性差
Spring 官方推荐:构造器注入用于强制依赖,Setter 注入用于可选依赖。
4.2 @Autowired 的工作原理
- 按类型(byType)匹配
- 找到多个同类型 Bean → 按名称(byName)匹配
- 都匹配不上 → 报错
NoUniqueBeanDefinitionException
// 场景:接口有多个实现
public interface Payment { }
@Component
public class Alipay implements Payment { }
@Component
public class WeChatPay implements Payment { }
// 解决方案
@Autowired
@Qualifier("weChatPay") // 方案1:指定 Bean 名称
private Payment payment;
// 或
@Primary // 方案2:标记首选实现
@Component
public class Alipay implements Payment { }
4.3 @Resource vs @Autowired
| 对比 |
@Autowired |
@Resource |
| 来源 |
Spring 注解 |
Java 标准(JSR-250) |
| 匹配规则 |
先 byType,再 byName |
先 byName,再 byType |
| 适用 |
Spring 项目 |
Java EE 通用 |
| 组合 |
常与 @Qualifier 配合 |
直接用 name 属性指定 |
@Resource(name = "weChatPay")
private Payment payment;
4.4 @Value 注入配置值
@Service
public class AppConfig {
@Value("${app.name}")
private String appName;
@Value("${app.version:1.0.0}") // 带默认值
private String version;
@Value("#{systemProperties['java.home']}") // SpEL 表达式
private String javaHome;
@Value("classpath:data.txt") // 注入 Resource
private Resource resource;
}
5. Spring AOP
5.1 什么是 AOP?
AOP(Aspect-Oriented Programming,面向切面编程):将横跨多个业务模块的公共逻辑(日志、事务、权限)抽取到"切面"中集中管理。
传统方式:
UserService.addUser() {
开启日志 ← 重复
开启事务 ← 重复
核心业务
提交事务 ← 重复
记录日志 ← 重复
}
AOP 方式:
切面:日志切面 切面:事务切面
│ │
└──────┬───────┘
▼
UserService.addUser()
│
▼
核心业务
5.2 AOP 核心术语
| 术语 |
英文 |
说明 |
| 切面 |
Aspect |
横切关注点的模块化(日志切面 = 日志逻辑 + 切入点) |
| 连接点 |
Join Point |
方法执行过程中的某个点 |
| 切入点 |
Pointcut |
匹配连接点的表达式,决定切面在哪些方法执行 |
| 通知 |
Advice |
切面在连接点执行的具体逻辑 |
| 目标对象 |
Target |
被增强的原始对象 |
| 代理 |
Proxy |
AOP 为目标对象创建的代理对象 |
| 织入 |
Weaving |
将切面应用到目标对象以创建代理的过程 |
5.3 五种通知类型
@Aspect
@Component
public class LogAspect {
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
// ① @Before:前置通知(方法执行前)
@Before("execution(* com.example.service.*.*(..))")
public void before(JoinPoint jp) {
log.info("方法执行前: {}", jp.getSignature());
}
// ② @After:后置通知(方法执行后,无论是否异常)
@After("execution(* com.example.service.*.*(..))")
public void after() {
log.info("方法执行后(一定会执行)");
}
// ③ @AfterReturning:返回通知(方法正常返回后)
@AfterReturning(value = "execution(* com.example.service.*.*(..))",
returning = "result")
public void afterReturning(Object result) {
log.info("方法返回: {}", result);
}
// ④ @AfterThrowing:异常通知(方法抛异常后)
@AfterThrowing(value = "execution(* com.example.service.*.*(..))",
throwing = "ex")
public void afterThrowing(Exception ex) {
log.error("方法异常: {}", ex.getMessage());
}
// ⑤ @Around:环绕通知(最强大)
@Around("@annotation(com.example.annotation.Monitor)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
log.info("环绕前");
Object result = pjp.proceed(); // 执行目标方法
log.info("环绕后");
return result;
} finally {
long cost = System.currentTimeMillis() - start;
log.info("耗时: {}ms", cost);
}
}
}
5.4 Pointcut 表达式
execution(修饰符? 返回类型 方法路径(参数) throws? )
// 匹配所有 public 方法
@Pointcut("execution(public * *(..))")
// 匹配指定包下所有类的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
// 匹配指定包及其子包
@Pointcut("execution(* com.example.service..*.*(..))")
// 匹配特定方法的特定方法
@Pointcut("execution(* com.example.service.UserService.findById(Long))")
// 匹配所有 Controller 方法
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
// 匹配自定义注解
@Pointcut("@annotation(com.example.annotation.Monitor)")
通配符:
| 符号 |
含义 |
* |
匹配任意字符(方法名、类名)或任意返回类型 |
.. |
匹配 0 个或多个参数,或匹配子包路径 |
5.5 复用 Pointcut
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {} // 定义切入点
@Before("serviceLayer()")
public void before() { ... }
@AfterReturning("serviceLayer()")
public void afterReturning() { ... }
@AfterThrowing("serviceLayer()")
public void afterThrowing() { ... }
}
5.6 自定义注解 + AOP(🔥 最实用)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Monitor {
String value() default "";
}
@Aspect
@Component
public class MonitorAspect {
@Around("@annotation(monitor)")
public Object monitor(ProceedingJoinPoint pjp, Monitor monitor) throws Throwable {
String methodName = pjp.getSignature().toShortString();
String desc = monitor.value().isEmpty() ? methodName : monitor.value();
System.out.println("═══════════════════════════════");
System.out.println(" 开始监控: " + desc);
long start = System.nanoTime();
try {
return pjp.proceed();
} catch (Exception e) {
System.err.println(" 监控异常: " + e.getMessage());
throw e;
} finally {
long cost = (System.nanoTime() - start) / 1_000_000;
System.out.println(" 耗时: " + cost + "ms");
System.out.println("═══════════════════════════════");
}
}
}
@Service
public class UserService {
@Monitor("查询用户")
public User findById(Long id) {
// ...
}
}
5.7 JDK 动态代理 vs CGLIB
| 对比 |
JDK 动态代理 |
CGLIB |
| 要求 |
目标类必须实现接口 |
无限制 |
| 原理 |
基于接口生成代理 |
基于继承生成子类 |
| 代理创建速度 |
快 |
稍慢 |
| 执行速度 |
稍慢 |
快 |
| Spring Boot 默认 |
❌ |
✅(spring.aop.proxy-target-class=true) |
// 强制使用 CGLIB
@EnableAspectJAutoProxy(proxyTargetClass = true)
6. Spring Bean 生命周期
6.1 完整生命周期(10步)
容器启动
│
▼
① 实例化 —— 构造器创建对象
│
▼
② 设置属性 —— 注入依赖
│
▼
③ 设置 Bean Name —— setBeanName()
│
▼
④ 设置 BeanFactory —— setBeanFactory()
│
▼
⑤ 设置 ApplicationContext —— setApplicationContext()
│
▼
⑥ BeanPostProcessor#postProcessBeforeInitialization —— 前置处理
│
▼
⑦ @PostConstruct / InitializingBean#afterPropertiesSet —— 初始化
│
▼
⑧ BeanPostProcessor#postProcessAfterInitialization —— 后置处理 ← AOP 在此创建代理
│
▼
⑨ Bean 就绪 —— 可用
│
▼
⑩ 容器关闭 —— @PreDestroy / DisposableBean#destroy —— 销毁
6.2 代码演示
@Component
public class LifecycleDemo implements InitializingBean, DisposableBean {
public LifecycleDemo() {
System.out.println("① 构造器:实例化");
}
@Autowired
public void setDependency() {
System.out.println("② 设置属性:依赖注入");
}
@PostConstruct
public void init() {
System.out.println("⑦ @PostConstruct:初始化");
}
@Override
public void afterPropertiesSet() {
System.out.println("⑦ InitializingBean:初始化");
}
@PreDestroy
public void preDestroy() {
System.out.println("⑩ @PreDestroy:销毁前");
}
@Override
public void destroy() {
System.out.println("⑩ DisposableBean:销毁");
}
}
6.3 BeanPostProcessor(扩展点)
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof UserService) {
System.out.println("初始化前: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof UserService) {
System.out.println("初始化后(AOP代理创建完成): " + beanName);
}
return bean;
}
}
6.4 循环依赖与三级缓存
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
三级缓存机制(仅 singleton 作用域有效):
第一级:singletonObjects ← 完全创建好的 Bean
第二级:earlySingletonObjects ← 提前暴露的"半成品"Bean
第三级:singletonFactories ← ObjectFactory,生成早期引用
流程:
1. 实例化 A → 暴露 A 到三级缓存 → 注入 B
2. 实例化 B → 暴露 B 到三级缓存 → 注入 A
3. B 从三级缓存拿到 A 的早期引用 → B 完成创建 → B 进入一级缓存
4. A 继续完成初始化 → A 进入一级缓存
⚠️ 构造器注入的循环依赖无法解决(实例化前无法暴露)。
7. Spring 配置管理
7.1 配置文件优先级
Spring Boot 配置加载顺序(从高到低):
1. 命令行参数 --server.port=8081
2. JNDI 属性
3. 系统属性 System.getProperties()
4. 环境变量
5. application-{profile}.properties (多环境配置)
6. application.properties (默认配置)
7. @PropertySource 注解
高优先级覆盖低优先级。
7.2 application.yml
server:
port: 8080
servlet:
context-path: /api
spring:
application:
name: demo-app
datasource:
url: jdbc:postgresql://localhost:5432/demo
username: postgres
password: 123456
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
# 自定义配置
app:
jwt:
secret: my-secret-key
expiration: 86400000
upload:
path: /data/uploads
7.3 多环境配置
# application-dev.yml(开发环境)
server:
port: 8080
spring:
datasource:
url: jdbc:h2:mem:testdb
# application-prod.yml(生产环境)
server:
port: 80
spring:
datasource:
url: jdbc:postgresql://prod-db:5432/db
# application.yml(激活 dev 环境)
spring:
profiles:
active: dev
# 命令行指定
java -jar app.jar --spring.profiles.active=prod
7.4 @ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "app.jwt")
public class JwtConfig {
private String secret;
private long expiration;
// getter / setter ...
}
app:
jwt:
secret: my-secret-key
expiration: 86400000
@Service
public class AuthService {
private final JwtConfig jwtConfig;
public AuthService(JwtConfig jwtConfig) {
this.jwtConfig = jwtConfig;
}
}
7.5 @PropertySource
@Configuration
@PropertySource("classpath:custom.properties")
public class CustomConfig {
@Value("${custom.key}")
private String customKey;
}
8. Spring MVC
8.1 Spring MVC 架构
用户请求
│
▼
DispatcherServlet(前端控制器)
│
▼
HandlerMapping(处理器映射器)
│ 根据 URL 找到对应的 Controller 方法
▼
Controller(处理器)
│ 执行业务逻辑,返回 ModelAndView
▼
ViewResolver(视图解析器)
│ 解析视图名称为实际视图
▼
View(渲染响应)
│
▼
返回响应
8.2 常用注解
@RestController // @Controller + @ResponseBody
@RequestMapping("/api/users") // 类级别 URL 映射
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// GET /api/users
@GetMapping
public Result<List<User>> list() {
return Result.success(userService.findAll());
}
// GET /api/users/{id}
@GetMapping("/{id}")
public Result<User> getById(@PathVariable Long id) {
return Result.success(userService.findById(id));
}
// POST /api/users
@PostMapping
public Result<User> create(@RequestBody @Valid UserCreateReq req) {
return Result.success(userService.create(req));
}
// PUT /api/users/{id}
@PutMapping("/{id}")
public Result<User> update(@PathVariable Long id,
@RequestBody @Valid UserUpdateReq req) {
return Result.success(userService.update(id, req));
}
// DELETE /api/users/{id}
@DeleteMapping("/{id}")
public Result<Void> delete(@PathVariable Long id) {
userService.delete(id);
return Result.success();
}
// 参数示例
@GetMapping("/search")
public Result<List<User>> search(
@RequestParam String keyword, // 查询参数
@RequestParam(defaultValue = "1") int page, // 带默认值
@RequestHeader("Authorization") String token // 请求头
) {
return Result.success(userService.search(keyword));
}
}
8.3 统一响应体
@Data
public class Result<T> {
private int code;
private String message;
private T data;
private long timestamp;
private Result() {
this.timestamp = System.currentTimeMillis();
}
public static <T> Result<T> success() {
Result<T> r = new Result<>();
r.code = 200;
r.message = "success";
return r;
}
public static <T> Result<T> success(T data) {
Result<T> r = success();
r.data = data;
return r;
}
public static <T> Result<T> error(int code, String message) {
Result<T> r = new Result<>();
r.code = code;
r.message = message;
return r;
}
}
8.4 统一异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
// 业务异常
@ExceptionHandler(BusinessException.class)
public Result<Void> handleBusiness(BusinessException e) {
log.warn("业务异常: {}", e.getMessage());
return Result.error(e.getCode(), e.getMessage());
}
// 参数校验失败
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidation(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getAllErrors()
.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(", "));
return Result.error(400, msg);
}
// 通用异常(兜底)
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
log.error("系统异常", e);
return Result.error(500, "服务器内部错误");
}
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
}
8.5 参数校验
@Data
public class UserCreateReq {
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度2-20个字符")
private String username;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
@NotNull(message = "年龄不能为空")
@Min(value = 0, message = "年龄不能小于0")
@Max(value = 150, message = "年龄不能大于150")
private Integer age;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
8.6 拦截器
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
// 请求到达 Controller 之前执行
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
throw new BusinessException(401, "未登录");
}
return true; // true 放行,false 拦截
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler, ModelAndView modelAndView) {
// Controller 执行后,视图渲染前
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) {
// 视图渲染后(清理资源)
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/auth/login", "/api/auth/register");
}
}
9. Spring Boot
9.1 Spring Boot 核心优势
| 特性 |
说明 |
| 自动配置 |
根据 classpath 依赖自动配置 Bean(如数据源、JPA) |
| 起步依赖 |
一组精心编排的依赖,一个 starter 解决一类问题 |
| 内嵌容器 |
内嵌 Tomcat / Jetty / Undertow,无需部署 WAR |
| Actuator |
生产级监控:健康检查、指标、审计、追踪 |
| 外部化配置 |
通过 application.yml 统一管理配置 |
9.2 项目初始化
<!-- Spring Boot 3.x 父 POM -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<dependencies>
<!-- Web 应用(内置 Tomcat) -->
<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>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
9.3 启动类
@SpringBootApplication // = @Configuration + @EnableAutoConfiguration + @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
9.4 常用 Starter 一览
| Starter |
用途 |
spring-boot-starter-web |
Web 应用(Tomcat + Spring MVC) |
spring-boot-starter-data-jpa |
JPA + Hibernate |
spring-boot-starter-data-redis |
Redis 操作 |
spring-boot-starter-security |
安全认证 |
spring-boot-starter-validation |
参数校验 |
spring-boot-starter-test |
单元测试(JUnit + Mockito) |
spring-boot-starter-amqp |
RabbitMQ |
spring-boot-starter-mail |
邮件发送 |
spring-boot-starter-cache |
缓存抽象 |
spring-boot-starter-actuator |
生产监控 |
9.5 自动配置原理
@SpringBootApplication
// ↓
@EnableAutoConfiguration
// ↓
@Import(AutoConfigurationImportSelector.class)
// ↓
// 读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// ↓
// 按条件(@ConditionalOnClass、@ConditionalOnMissingBean 等)加载配置
条件注解:
@ConditionalOnClass(RedisTemplate.class) // classpath 存在某类才加载
@ConditionalOnMissingBean(RedisTemplate.class) // 容器中没有某 Bean 才加载
@ConditionalOnProperty(prefix = "spring.redis", name = "enabled", havingValue = "true")
@ConditionalOnWebApplication // Web 应用才加载
9.6 Actuator 监控
spring:
boot:
actuator:
enabled: true
management:
endpoints:
web:
exposure:
include: health,info,metrics,loggers
endpoint:
health:
show-details: always
常用端点:
| 端点 |
路径 |
说明 |
health |
/actuator/health |
健康检查(数据库、Redis 等) |
info |
/actuator/info |
应用信息 |
metrics |
/actuator/metrics |
指标(JVM、内存、线程等) |
loggers |
/actuator/loggers |
运行时修改日志级别 |
env |
/actuator/env |
环境属性 |
mappings |
/actuator/mappings |
所有 URL 映射 |
9.7 Spring Boot 3.x 新特性
| 特性 |
说明 |
| Java 17+ 基线 |
强制 JDK 17,支持 Records、Sealed Class |
| GraalVM 原生编译 |
通过 AOT 编译为原生镜像,启动毫秒级 |
| 虚拟线程 |
通过 spring.threads.virtual.enabled=true 启用 |
| Problem Details |
RFC 9457 标准错误响应 |
| 可观测性 |
Micrometer 集成,OpenTelemetry 支持 |
10. Spring Data JPA
10.1 实体映射
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true, length = 50)
private String username;
@Column(nullable = false)
private String password;
@Column(length = 100)
private String email;
@Enumerated(EnumType.STRING)
private Sex sex;
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
public enum Sex {
MALE, FEMALE
}
}
10.2 Repository 接口
// 基础 CRUD(MyBatis-Plus 的 JPA 版)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 根据方法名自动生成 SQL
Optional<User> findByUsername(String username);
List<User> findByEmailContaining(String keyword);
boolean existsByUsername(String username);
long countBySex(User.Sex sex);
// 自定义 JPQL 查询
@Query("SELECT u FROM User u WHERE u.email LIKE %:domain% ORDER BY u.createdAt DESC")
List<User> findByEmailDomain(@Param("domain") String domain);
// 原生 SQL 查询
@Query(value = "SELECT * FROM users WHERE username LIKE :keyword LIMIT :limit",
nativeQuery = true)
List<User> searchByUsername(@Param("keyword") String keyword,
@Param("limit") int limit);
// 修改操作需要用 @Modifying
@Modifying
@Query("UPDATE User u SET u.email = :email WHERE u.username = :username")
int updateEmail(@Param("username") String username, @Param("email") String email);
}
10.3 JPA 方法命名规则
findBy + 字段名 + 操作符 + And/Or + 字段名 + 操作符
| 关键字 |
示例 |
JPQL 片段 |
And |
findByNameAndAge |
WHERE name=?1 AND age=?2 |
Or |
findByNameOrEmail |
WHERE name=?1 OR email=?2 |
Is |
findByNameIs |
WHERE name=?1 |
Not |
findByNameNot |
WHERE name<>?1 |
Between |
findByAgeBetween |
WHERE age BETWEEN ?1 AND ?2 |
LessThan |
findByAgeLessThan |
WHERE age < ?1 |
GreaterThan |
findByAgeGreaterThan |
WHERE age > ?1 |
Like |
findByNameLike |
WHERE name LIKE ?1 |
Containing |
findByNameContaining |
WHERE name LIKE %?1% |
In |
findByAgeIn |
WHERE age IN (?1) |
OrderBy |
findByAgeOrderByNameDesc |
WHERE age=?1 ORDER BY name DESC |
10.4 关联映射
// 一对一:User ↔ IdCard
@Entity
public class IdCard {
@Id private Long id;
private String cardNumber;
@OneToOne(mappedBy = "idCard")
private User user;
}
// 一对多:User ↔ Order
@Entity
public class User {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Order> orders;
}
// 多对一:Order ↔ User
@Entity
public class Order {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
}
// 多对多:User ↔ Role
@Entity
public class User {
@ManyToMany
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
}
10.5 分页查询
// Service 层
public Page<User> findByPage(String keyword, int pageNum, int pageSize) {
Pageable pageable = PageRequest.of(pageNum - 1, pageSize, Sort.by("createdAt").descending());
return userRepository.findByUsernameContaining(keyword, pageable);
}
// Controller
@GetMapping
public Result<Page<User>> list(
@RequestParam(defaultValue = "") String keyword,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return Result.success(userService.findByPage(keyword, page, size));
}
10.6 复杂查询(Specification / JPA Criteria)
// 动态多条件查询
@Service
public class UserService {
public List<User> findByConditions(String name, Integer minAge, String email) {
Specification<User> spec = Specification.where(null);
if (name != null && !name.isEmpty()) {
spec = spec.and((root, query, cb) ->
cb.like(root.get("name"), "%" + name + "%"));
}
if (minAge != null) {
spec = spec.and((root, query, cb) ->
cb.greaterThanOrEqualTo(root.get("age"), minAge));
}
if (email != null) {
spec = spec.and((root, query, cb) ->
cb.equal(root.get("email"), email));
}
return userRepository.findAll(spec, Sort.by("createdAt").descending());
}
}
11. Spring Data Redis
11.1 配置
spring:
data:
redis:
host: localhost
port: 6379
password:
timeout: 3000ms
lettuce:
pool:
max-active: 16
max-idle: 8
min-idle: 4
11.2 使用 RedisTemplate
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// String 操作
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public <T> T get(String key) {
return (T) redisTemplate.opsForValue().get(key);
}
// Hash 操作
public void hSet(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
public Object hGet(String key, String field) {
return redisTemplate.opsForHash().get(key, field);
}
// List 操作
public void lPush(String key, Object value) {
redisTemplate.opsForList().leftPush(key, value);
}
// Set 操作
public void sAdd(String key, Object... values) {
redisTemplate.opsForSet().add(key, values);
}
// ZSet 操作
public void zAdd(String key, Object value, double score) {
redisTemplate.opsForZSet().add(key, value, score);
}
// 设置过期时间
public void expire(String key, long timeout, TimeUnit unit) {
redisTemplate.expire(key, timeout, unit);
}
// 删除
public void delete(String key) {
redisTemplate.delete(key);
}
}
11.3 缓存注解
@Service
@CacheConfig(cacheNames = "users")
public class UserService {
// 查缓存,没有则执行方法并缓存结果
@Cacheable(key = "#id")
public User findById(Long id) {
return userRepository.findById(id).orElse(null);
}
// 更新数据时同步更新缓存
@CachePut(key = "#user.id")
public User update(User user) {
return userRepository.save(user);
}
// 删除数据时清除缓存
@CacheEvict(key = "#id")
public void delete(Long id) {
userRepository.deleteById(id);
}
// 清除所有 users 缓存
@CacheEvict(allEntries = true)
public void clearCache() { }
}
11.4 缓存配置
spring:
cache:
type: redis # 默认使用 ConcurrentHashMap 缓存,改为 Redis
12. Spring 事务管理
12.1 @Transactional
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryService inventoryService;
// 默认只回滚 RuntimeException
@Transactional
public Order createOrder(Order order) {
// 扣减库存
inventoryService.deduct(order.getProductId(), order.getQuantity());
// 保存订单
return orderRepository.save(order);
}
}
12.2 @Transactional 参数
| 参数 |
说明 |
默认值 |
propagation |
事务传播行为 |
REQUIRED |
isolation |
事务隔离级别 |
数据库默认 |
timeout |
超时时间(秒) |
-1(不超时) |
readOnly |
是否只读 |
false |
rollbackFor |
回滚异常类型 |
RuntimeException |
noRollbackFor |
不回滚的异常 |
空 |
@Transactional(
propagation = Propagation.REQUIRED, // 需要事务(默认)
isolation = Isolation.READ_COMMITTED, // 读已提交
timeout = 30,
rollbackFor = { BusinessException.class, DataAccessException.class },
readOnly = false
)
public void transfer(Long fromId, Long toId, BigDecimal amount) { }
12.3 事务传播行为
| 传播行为 |
说明 |
REQUIRED(默认) |
有事务则加入,无则创建新事务 |
REQUIRES_NEW |
挂起当前事务,创建新事务 |
SUPPORTS |
有事务则加入,无则以非事务方式执行 |
NOT_SUPPORTED |
以非事务方式执行,挂起当前事务 |
MANDATORY |
必须在事务中执行,无事务则抛异常 |
NEVER |
必须在非事务中执行,有事务则抛异常 |
NESTED |
嵌套事务(JDBC Savepoint) |
@Service
public class OrderService {
@Autowired
private LogService logService;
@Transactional
public void createOrder() {
// 订单业务...
// 日志记录独立事务(即使订单失败,日志也要记录)
logService.saveLog("创建订单");
}
}
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(String message) {
// 此方法在独立事务中执行
}
}
12.4 事务失效场景
// ❌ 场景1:同一类中方法内部调用
@Service
public class UserService {
@Transactional
public void methodA() {
// 调用 methodB 时,事务不生效(this 指向原始对象,不是代理)
methodB();
}
@Transactional
public void methodB() { }
// ✅ 解决方案:注入自身
@Autowired
private UserService self;
@Transactional
public void methodA() {
self.methodB(); // 通过代理调用
}
}
// ❌ 场景2:异常被 try-catch 吞掉
@Transactional
public void method() {
try {
// 业务逻辑
} catch (Exception e) {
// 异常被捕获,事务不会回滚
}
}
// ❌ 场景3:非 public 方法
@Transactional
protected void method() { } // 默认不回滚
// ❌ 场景4:数据库引擎不支持事务(MyISAM)
12.5 编程式事务
@Service
public class UserService {
@Autowired
private TransactionTemplate transactionTemplate;
public void saveInTransaction(User user) {
transactionTemplate.execute(status -> {
try {
userRepository.save(user);
return null;
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
});
}
}
13. Spring Security
13.1 核心概念
Spring Security 过滤器链:
请求 → SecurityContextPersistenceFilter
→ UsernamePasswordAuthenticationFilter(登录认证)
→ BasicAuthenticationFilter
→ AnonymousAuthenticationFilter
→ ExceptionTranslationFilter
→ FilterSecurityInterceptor(授权验证)
→ 最终到达 Controller
13.2 基础配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// 禁用 CSRF(REST API 不需要)
.csrf(AbstractHttpConfigurer::disable)
// 请求授权
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() // 登录注册放行
.requestMatchers("/actuator/**").permitAll() // 监控端点放行
.requestMatchers(HttpMethod.GET, "/api/articles").permitAll() // 公开 GET
.requestMatchers("/api/admin/**").hasRole("ADMIN") // 管理员权限
.anyRequest().authenticated() // 其他需登录
)
// 无状态 Session(JWT 不需要 Session)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
// 自定义异常处理
.exceptionHandling(ex -> ex
.authenticationEntryPoint((request, response, authException) ->
response.getWriter().write("未登录"))
.accessDeniedHandler((request, response, accessDeniedException) ->
response.getWriter().write("无权限")));
return http.build();
}
// 密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
13.3 JWT 认证
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String token = extractToken(request);
if (token != null && jwtUtil.validateToken(token)) {
String username = jwtUtil.getUsername(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
private String extractToken(HttpServletRequest request) {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
return header.substring(7);
}
return null;
}
}
13.4 方法级别安全
@EnableMethodSecurity // 开启方法级别安全
@Configuration
public class SecurityConfig { }
@RestController
@RequestMapping("/api/admin")
public class AdminController {
// 需要 ADMIN 角色
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/users")
public List<User> listUsers() { return ...; }
// 多个条件
@PreAuthorize("hasRole('ADMIN') and #id != authentication.principal.id")
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) { ... }
// SpEL 表达式
@PreAuthorize("hasAuthority('user:delete')")
@PostMapping("/users")
public void createUser(@Valid @RequestBody User user) { ... }
// POST 授权
@PostAuthorize("returnObject.owner == authentication.principal.username")
public User getUser(@PathVariable Long id) { return ...; }
}
14. Spring Cloud 微服务
14.1 微服务架构总览
外部请求
│
▼
┌─────────────────────────────────────┐
│ API 网关(Gateway) │
│ 路由转发 · 限流 · 鉴权 · 日志 │
└────────┬──────┬──────┬─────────────┘
│ │ │
┌────▼──┐ ┌▼─────┐ ┌▼─────┐
│用户服务│ │订单服务│ │商品服务│
│User │ │Order │ │Product│
└───┬───┘ └──┬───┘ └──┬───┘
│ │ │
┌───┴────────┴────────┴───┐
│ 注册中心(Nacos) │
│ 配置中心(Nacos) │
└────────────────────────┘
14.2 常用组件
| 组件 |
说明 |
| Nacos |
注册中心 + 配置中心(替代 Eureka + Config) |
| Gateway |
API 网关(路由、限流、过滤) |
| OpenFeign |
声明式服务调用 |
| LoadBalancer |
客户端负载均衡(替代 Ribbon) |
| Sentinel |
流量控制、熔断降级(替代 Hystrix) |
| Sleuth + Zipkin |
链路追踪 |
| Seata |
分布式事务 |
14.3 Nacos 注册中心
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
service: user-service
14.4 OpenFeign 服务调用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@FeignClient(name = "order-service", path = "/api/orders")
public interface OrderFeignClient {
@GetMapping("/{id}")
Result<Order> getById(@PathVariable Long id);
@GetMapping("/user/{userId}")
Result<List<Order>> listByUserId(@PathVariable Long userId);
}
@Service
public class UserService {
@Autowired
private OrderFeignClient orderFeignClient;
public UserVO getUserWithOrders(Long userId) {
User user = userRepository.findById(userId).orElseThrow();
List<Order> orders = orderFeignClient.listByUserId(userId);
return new UserVO(user, orders);
}
}
14.5 Sentinel 熔断降级
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
@Service
public class UserService {
@SentinelResource(value = "getUser",
fallback = "fallbackGetUser",
blockHandler = "blockGetUser")
public User getById(Long id) {
return userRepository.findById(id).orElseThrow();
}
// 业务异常降级
public User fallbackGetUser(Long id, Throwable t) {
return new User(); // 返回默认对象
}
// 限流异常降级
public User blockGetUser(Long id, BlockException e) {
return new User(); // 被限流时的响应
}
}
15. Spring 单元测试
15.1 基础测试
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
@SpringBootTest // 启动完整 Spring 容器
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void testFindById() {
User user = userService.findById(1L);
assertNotNull(user);
assertEquals("Alice", user.getUsername());
}
}
15.2 Slice 测试(只加载部分容器)
// 只加载 Web 层
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void testList() throws Exception {
when(userService.findAll()).thenReturn(List.of(new User()));
mockMvc.perform(get("/api/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));
}
}
// 只加载 JPA 层
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void testFindByUsername() {
User user = userRepository.findByUsername("Alice");
assertNotNull(user);
}
}
15.3 Mockito 使用
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void testFindById() {
// 模拟返回
when(userRepository.findById(1L))
.thenReturn(Optional.of(new User(1L, "Alice")));
// 执行
User user = userService.findById(1L);
// 验证
assertNotNull(user);
assertEquals("Alice", user.getUsername());
// 验证方法是否被调用
verify(userRepository).findById(1L);
}
}
15.4 测试数据库
# application-test.yml
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create-drop
@ActiveProfiles("test")
@SpringBootTest
class UserServiceTest { ... }
16. 最佳实践与常见问题
16.1 最佳实践
// 1. 构造器注入(优先于字段注入)
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
// 2. 统一异常处理(不用每个 Controller 写 try-catch)
@RestControllerAdvice
public class GlobalExceptionHandler { ... }
// 3. 统一响应格式
@Data
public class Result<T> { ... }
// 4. 使用 DTO 而不是直接把 Entity 暴露出去
@Data
public class UserVO { ... }
// 5. 异步方法放在单独 Bean 中调用
@Service
public class AsyncService {
@Async
public void sendEmail(String to) { ... }
}
@Service
public class UserService {
@Autowired private AsyncService asyncService;
public void register(User user) {
// ...
asyncService.sendEmail(user.getEmail()); // 通过代理调用
}
}
// 6. 配置懒加载提升启动速度
spring:
main:
lazy-initialization: true
// 7. 分页参数从0开始(PageRequest.of 使用 0-based page)
Pageable pageable = PageRequest.of(0, 10); // 第1页
16.2 常见问题
Q1:Spring Boot 启动失败——端口被占用
# 查找端口占用
netstat -ano | findstr :8080
taskkill /PID <PID> /F
# 或修改端口
server.port=8081
Q2:@Transactional 事务不生效
- 检查是否在非 public 方法上使用 ✅ 只在 public 方法用
- 检查是否内部调用 ✅ 通过代理调用
- 检查异常是否被捕获 ✅ 不要吞异常
- 检查数据库引擎 ✅ 用 InnoDB(MySQL)
Q3:注入报错 NoUniqueBeanDefinitionException
// 有多个同类型 Bean 时,用 @Qualifier 指定
@Autowired
@Qualifier("userServiceImpl")
private UserService userService;
Q4:Spring Security 放行失败
// 确保放行路径在拦截规则前面
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() // 放行先写
.anyRequest().authenticated() // 拦截后写
)
Q5:跨域问题(CORS)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}
16.3 阿里规约精选
// 1. 禁止使用 @Autowired 字段注入(建议构造器注入)
// ❌
@Autowired private UserService userService;
// ✅
private final UserService userService;
public XxxController(UserService userService) { this.userService = userService; }
// 2. 类名用单数
UserService // ✅
UsersService // ❌
// 3. 接口名用 I 前缀或不带前缀
IUserService // ✅
UserService // ✅
// 4. 避免使用 @PostConstruct 做大量初始化(可用 CommandLineRunner)
@Component
public class DataInitializer implements CommandLineRunner {
@Override
public void run(String... args) {
// 启动初始化逻辑
}
}
// 5. 禁止使用 System.out.println(用 Logger)
private static final Logger log = LoggerFactory.getLogger(Xxx.class);
17. 附录:速查表
17.1 注解速查
IoC / DI
| 注解 |
用途 |
@Component |
通用组件 |
@Service |
业务层 |
@Repository |
数据访问层 |
@Controller |
控制层 |
@RestController |
REST 控制层 |
@Configuration |
配置类 |
@Bean |
声明 Bean(配置类中使用) |
@Autowired |
依赖注入 |
@Qualifier |
指定 Bean 名称 |
@Value |
注入配置值 |
@Scope |
作用域 |
@Lazy |
延迟初始化 |
@Primary |
首选 Bean |
Web
| 注解 |
用途 |
@RequestMapping |
URL 映射 |
@GetMapping |
GET 请求 |
@PostMapping |
POST 请求 |
@PutMapping |
PUT 请求 |
@DeleteMapping |
DELETE 请求 |
@PathVariable |
路径参数 |
@RequestParam |
查询参数 |
@RequestBody |
请求体 |
@RequestHeader |
请求头 |
@ResponseBody |
返回 JSON |
@RestControllerAdvice |
统一异常处理 |
AOP
| 注解 |
用途 |
@Aspect |
声明切面 |
@Pointcut |
定义切入点 |
@Before |
前置通知 |
@After |
后置通知 |
@AfterReturning |
返回通知 |
@AfterThrowing |
异常通知 |
@Around |
环绕通知 |
数据
| 注解 |
用途 |
@Transactional |
声明事务 |
@Cacheable |
缓存(查) |
@CachePut |
缓存(更新) |
@CacheEvict |
清除缓存 |
@EnableCaching |
开启缓存 |
条件装配
| 注解 |
用途 |
@ConditionalOnClass |
classpath 存在某类 |
@ConditionalOnMissingBean |
容器中缺少某 Bean |
@ConditionalOnProperty |
配置属性匹配 |
@ConditionalOnWebApplication |
Web 应用 |
@Profile |
指定环境 |
17.2 配置项速查
# 服务器
server.port=8080
server.servlet.context-path=/api
# 数据源
spring.datasource.url=jdbc:postgresql://localhost:5432/db
spring.datasource.username=postgres
spring.datasource.password=123456
spring.datasource.driver-class-name=org.postgresql.Driver
# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
# Redis
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.timeout=3000ms
# 多环境
spring.profiles.active=dev
# Actuator
management.endpoints.web.exposure.include=health,info,metrics
17.3 常用 Starter
spring-boot-starter-web Web 应用
spring-boot-starter-data-jpa JPA + Hibernate
spring-boot-starter-data-redis Redis
spring-boot-starter-security 安全认证
spring-boot-starter-validation 参数校验
spring-boot-starter-test 单元测试
spring-boot-starter-actuator 生产监控
spring-boot-starter-mail 邮件发送
spring-boot-starter-cache 缓存
spring-boot-starter-amqp RabbitMQ
spring-boot-starter-quartz 定时任务
17.4 推荐学习路径
1️⃣ Spring Framework 基础
├── IoC 容器 / DI 依赖注入
├── AOP 面向切面编程
└── Bean 生命周期
2️⃣ Spring Boot
├── 自动配置原理
├── 起步依赖
├── 配置文件管理
└── Actuator 监控
3️⃣ Spring MVC
├── RESTful API
├── 参数校验
├── 统一异常处理
└── 拦截器 / 过滤器
4️⃣ 数据访问
├── Spring Data JPA
├── Spring Data Redis
└── 事务管理
5️⃣ 安全
├── Spring Security 基础
├── JWT 认证
└── 方法级别安全
6️⃣ 微服务(进阶)
├── Nacos 注册/配置中心
├── Gateway 网关
├── OpenFeign 服务调用
├── Sentinel 熔断降级
└── Seata 分布式事务
写在最后:Spring 全家桶的核心是 简化开发。初学时不必追求面面俱到,建议先掌握 IoC/DI 和 AOP 这两个核心思想,然后从 Spring Boot 入手快速构建项目,在实践中逐步深入。祝编码愉快!🚀
Comments | 0条评论