
在Java企业级开发领域,Spring框架无疑是当之无愧的基石。无论是微服务架构、分布式系统,还是传统的单体应用,Spring都以其强大的扩展性、灵活性和易用性,成为开发者的首选框架。但很多开发者在使用Spring时,往往停留在“API调用”层面,对其底层体系结构、核心设计思想一知半解,导致遇到复杂问题时难以定位,更无法充分发挥Spring的强大能力。
Spring并非单一框架,而是一个庞大的生态体系,核心围绕“简化Java开发”这一目标展开。其整体架构采用分层设计和模块化拆分,既保证了核心功能的简洁性,又通过扩展模块满足不同场景的需求。

Spring的所有功能都构建在两大核心思想之上,这也是理解整个Spring体系的关键:
这两大思想贯穿于Spring的所有核心模块,是Spring生态的“灵魂”。后续所有模块的解析,都会围绕这两个核心展开。
核心容器(Core Container)是Spring的基础,负责对象的创建、管理和依赖注入,是所有其他模块的支撑。包含Beans、Core、Context、Expression Language四个子模块。
Core模块提供了Spring框架的基础工具类,是整个Spring的“工具包”,其他模块都依赖于它。核心功能包括:
package com.jam.demo.core;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.FileCopyUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* Spring Core模块资源访问示例
* @author ken
*/
@Slf4j
publicclass ResourceDemo {
public static void main(String[] args) {
// 访问类路径下的配置文件
Resource resource = new ClassPathResource("application.properties");
try {
// 使用Spring工具类读取文件内容
byte[] content = FileCopyUtils.copyToByteArray(resource.getInputStream());
String contentStr = new String(content, StandardCharsets.UTF_8);
log.info("配置文件内容:\n{}", contentStr);
} catch (IOException e) {
log.error("读取配置文件失败", e);
}
}
}
Beans模块是IOC思想的核心实现,负责Bean的定义、创建、注册和管理。核心概念包括:
package com.jam.demo.beans;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
/**
* BeanFactory手动管理Bean示例
* @author ken
*/
@Slf4j
publicclass BeanFactoryDemo {
public static void main(String[] args) {
// 1. 创建BeanFactory实例(默认实现类)
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 定义BeanDefinition(描述UserService)
BeanDefinition userServiceDefinition = new RootBeanDefinition(UserService.class);
// 3. 向BeanFactory注册Bean
beanFactory.registerBeanDefinition("userService", userServiceDefinition);
// 4. 从BeanFactory获取Bean(此时才创建Bean实例,懒加载)
UserService userService = beanFactory.getBean("userService", UserService.class);
userService.sayHello("Spring Beans");
// 5. 验证单例特性(多次获取为同一实例)
UserService userService2 = beanFactory.getBean("userService", UserService.class);
log.info("是否为同一实例:{}", userService == userService2);
}
/**
* 测试Bean类
* @author ken
*/
@Data
publicstaticclass UserService {
public void sayHello(String name) {
log.info("Hello, {}! 这是BeanFactory创建的Bean", name);
}
}
}
Context模块基于Core和Beans模块,提供了更强大的应用上下文管理功能,是BeanFactory的增强版。核心优势:

package com.jam.demo.context;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 注解驱动的应用上下文示例
* @author ken
*/
@Slf4j
publicclass AnnotationContextDemo {
public static void main(String[] args) {
// 1. 创建注解驱动的应用上下文,扫描指定包下的注解Bean
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 2. 获取Bean(UserService被@Bean注解定义)
UserService userService = context.getBean(UserService.class);
userService.queryUser("1001");
// 3. 关闭上下文
context.close();
}
/**
* 应用配置类,用于定义Bean
* @author ken
*/
@Configuration
publicstaticclass AppConfig {
/**
* 定义UserService Bean
* @return UserService实例
*/
@Bean
public UserService userService() {
returnnew UserService();
}
}
/**
* 用户服务类
* @author ken
*/
publicstaticclass UserService {
public void queryUser(String userId) {
log.info("查询用户信息,用户ID:{}", userId);
}
}
}
Spring EL(SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象。核心功能包括:
package com.jam.demo.el;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.ArrayList;
import java.util.List;
/**
* Spring EL表达式示例
* @author ken
*/
@Slf4j
publicclass Speldemo {
public static void main(String[] args) {
// 1. 创建SpEL解析器
ExpressionParser parser = new SpelExpressionParser();
// 2. 简单表达式:算术运算
Expression exp1 = parser.parseExpression("100 + 200 * 3");
Integer result1 = exp1.getValue(Integer.class);
log.info("算术运算结果:{}", result1);
// 3. 访问对象属性和方法
User user = new User("张三", 25);
StandardEvaluationContext context = new StandardEvaluationContext(user);
Expression exp2 = parser.parseExpression("name");
String userName = exp2.getValue(context, String.class);
log.info("用户姓名:{}", userName);
Expression exp3 = parser.parseExpression("getName().toUpperCase()");
String upperName = exp3.getValue(context, String.class);
log.info("姓名大写:{}", upperName);
// 4. 集合操作
List<String> list = new ArrayList<>();
list.add("Spring");
list.add("Spring Boot");
list.add("Spring Cloud");
context.setVariable("list", list);
Expression exp4 = parser.parseExpression("#list.stream().filter(s -> s.startsWith('Spring ')).collect(toList())");
List<String> resultList = exp4.getValue(context, List.class);
log.info("集合过滤结果:{}", resultList);
}
/**
* 测试用户类
* @author ken
*/
@Data
publicstaticclass User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
}
}
AOP模块是Spring实现面向切面编程的核心,通过动态代理技术,在不修改原有代码的前提下,为程序添加通用功能(如日志、事务、权限)。核心依赖于Core和Beans模块。
Spring AOP默认使用JDK动态代理(针对接口),如果目标对象没有实现接口,则使用CGLIB动态代理(通过继承目标类)。核心流程:

<!-- Spring AOP核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.1.5</version>
</dependency>
<!-- AspectJ支持(Spring AOP依赖AspectJ表达式) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.21</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
package com.jam.demo.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Arrays;
/**
* 日志切面类,用于增强服务层方法的日志输出
* @author ken
*/
@Aspect
@Component
@Slf4j
publicclass LogAspect {
/**
* 切入点表达式:匹配com.jam.demo.service包下所有类的所有公共方法
*/
@Pointcut("execution(public * com.jam.demo.service..*(..))")
public void servicePointcut() {}
/**
* 前置通知:方法执行前执行
* @param joinPoint 连接点对象,包含方法信息、参数等
*/
@Before("servicePointcut()")
public void beforeAdvice(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
Object[] args = joinPoint.getArgs();
log.info("【前置通知】{}类的{}方法开始执行,参数:{}", className, methodName, Arrays.toString(args));
}
/**
* 后置通知:方法执行后执行(无论成功与否)
* @param joinPoint 连接点对象
*/
@After("servicePointcut()")
public void afterAdvice(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
log.info("【后置通知】{}类的{}方法执行结束", className, methodName);
}
/**
* 返回通知:方法成功执行后执行,可获取返回值
* @param joinPoint 连接点对象
* @param result 方法返回值
*/
@AfterReturning(pointcut = "servicePointcut()", returning = "result")
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
log.info("【返回通知】{}类的{}方法执行成功,返回值:{}", className, methodName, result);
}
/**
* 异常通知:方法执行异常时执行
* @param joinPoint 连接点对象
* @param e 异常对象
*/
@AfterThrowing(pointcut = "servicePointcut()", throwing = "e")
public void afterThrowingAdvice(JoinPoint joinPoint, Exception e) {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
log.error("【异常通知】{}类的{}方法执行异常,异常信息:{}", className, methodName, e.getMessage(), e);
}
/**
* 环绕通知:包围方法执行,可控制方法是否执行、执行时机
* @param proceedingJoinPoint 可执行的连接点对象
* @return 方法返回值
* @throws Throwable 方法执行异常
*/
@Around("servicePointcut()")
public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
String methodName = proceedingJoinPoint.getSignature().getName();
String className = proceedingJoinPoint.getTarget().getClass().getSimpleName();
long startTime = System.currentTimeMillis();
Object result = null;
try {
// 执行前置逻辑
log.info("【环绕通知-前置】{}类的{}方法开始计时", className, methodName);
// 执行目标方法
result = proceedingJoinPoint.proceed();
// 执行返回后逻辑
log.info("【环绕通知-返回】{}类的{}方法计时结束", className, methodName);
} catch (Exception e) {
// 执行异常逻辑
log.error("【环绕通知-异常】{}类的{}方法执行异常", className, methodName, e);
throw e;
} finally {
// 计算方法执行时间
long costTime = System.currentTimeMillis() - startTime;
log.info("【环绕通知-最终】{}类的{}方法执行耗时:{}ms", className, methodName, costTime);
}
return result;
}
}
package com.jam.demo.service;
import com.jam.demo.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
/**
* 用户服务类,被AOP增强
* @author ken
*/
@Service
@Slf4j
publicclass UserService {
/**
* 根据用户ID查询用户
* @param userId 用户ID
* @return User对象
*/
public User queryUserById(String userId) {
// 模拟参数校验
if (ObjectUtils.isEmpty(userId)) {
thrownew IllegalArgumentException("用户ID不能为空");
}
// 模拟数据库查询
User user = new User();
user.setUserId(userId);
user.setUserName("张三");
user.setAge(25);
user.setPhone("13800138000");
return user;
}
/**
* 新增用户
* @param user 用户对象
* @return 新增成功的用户ID
*/
public String addUser(User user) {
// 模拟参数校验
if (ObjectUtils.isEmpty(user) || !org.springframework.util.StringUtils.hasText(user.getUserName())) {
thrownew IllegalArgumentException("用户名不能为空");
}
// 模拟数据库新增
String userId = "user_" + System.currentTimeMillis();
user.setUserId(userId);
log.info("用户新增成功,用户信息:{}", user);
return userId;
}
}
package com.jam.demo.entity;
import lombok.Data;
/**
* 用户实体类
* @author ken
*/
@Data
publicclass User {
/**
* 用户ID
*/
private String userId;
/**
* 用户名
*/
private String userName;
/**
* 年龄
*/
private Integer age;
/**
* 手机号
*/
private String phone;
}
package com.jam.demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* 应用配置类,开启AOP自动代理并扫描组件
* @author ken
*/
@Configuration
@ComponentScan(basePackages = "com.jam.demo")
@EnableAspectJAutoProxy(proxyTargetClass = true) // proxyTargetClass=true:强制使用CGLIB代理
public class AopConfig {
}
package com.jam.demo.aop;
import com.jam.demo.config.AopConfig;
import com.jam.demo.entity.User;
import com.jam.demo.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* AOP测试类
* @author ken
*/
publicclass AopTest {
public static void main(String[] args) {
// 初始化Spring上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
// 获取UserService代理对象
UserService userService = context.getBean(UserService.class);
// 测试正常方法调用
System.out.println("===== 测试查询用户 =====");
User user = userService.queryUserById("1001");
// 测试新增用户
System.out.println("\n===== 测试新增用户 =====");
User newUser = new User();
newUser.setUserName("李四");
newUser.setAge(30);
newUser.setPhone("13900139000");
userService.addUser(newUser);
// 测试异常情况
System.out.println("\n===== 测试参数异常 =====");
try {
userService.queryUserById(null);
} catch (Exception e) {
// 异常已被切面捕获并日志输出
}
// 关闭上下文
context.close();
}
}
数据访问/集成模块提供了Spring对数据访问层的支持,简化了JDBC、ORM框架(MyBatis、Hibernate)、事务管理等操作。核心模块包括JDBC、ORM、Transactions等。
Spring事务管理是该模块的核心功能,通过AOP实现声明式事务(注解@Transactional)或编程式事务,支持多种事务管理器(JDBC事务、JTA事务等)。
<!-- Spring 事务核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>6.1.5</version>
</dependency>
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.1.5</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!-- HikariCP连接池(Spring默认) -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>
<!-- FastJSON2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.45</version>
</dependency>
<!-- Google Guava 集合工具 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.1-jre</version>
</dependency>
<!-- Swagger3 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
-- 用户表
CREATETABLE`t_user` (
`user_id`varchar(64) NOTNULLCOMMENT'用户ID',
`user_name`varchar(32) NOTNULLCOMMENT'用户名',
`age`intDEFAULTNULLCOMMENT'年龄',
`phone`varchar(20) DEFAULTNULLCOMMENT'手机号',
`create_time` datetime NOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='用户表';
-- 订单表
CREATETABLE`t_order` (
`order_id`varchar(64) NOTNULLCOMMENT'订单ID',
`user_id`varchar(64) NOTNULLCOMMENT'用户ID',
`order_amount`decimal(10,2) NOTNULLCOMMENT'订单金额',
`create_time` datetime NOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',
PRIMARY KEY (`order_id`),
KEY`idx_user_id` (`user_id`)
) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='订单表';
package com.jam.demo.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 订单实体类
* @author ken
*/
@Data
@TableName("t_order")
publicclass Order {
/**
* 订单ID
*/
@TableId("order_id")
private String orderId;
/**
* 用户ID
*/
@TableField("user_id")
private String userId;
/**
* 订单金额
*/
@TableField("order_amount")
private BigDecimal orderAmount;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
}
package com.jam.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jam.demo.entity.Order;
import com.jam.demo.entity.User;
import org.springframework.stereotype.Repository;
/**
* 订单Mapper
* @author ken
*/
@Repository
public interface OrderMapper extends BaseMapper<Order> {
}
package com.jam.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jam.demo.entity.User;
import org.springframework.stereotype.Repository;
/**
* 用户Mapper
* @author ken
*/
@Repository
public interface UserMapper extends BaseMapper<User> {
}
package com.jam.demo.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jam.demo.entity.Order;
import com.jam.demo.entity.User;
import com.jam.demo.mapper.OrderMapper;
import com.jam.demo.mapper.UserMapper;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
/**
* 订单服务类(编程式事务)
* @author ken
*/
@Service
@Slf4j
@RequiredArgsConstructor
publicclass OrderService {
privatefinal OrderMapper orderMapper;
privatefinal UserMapper userMapper;
privatefinal PlatformTransactionManager transactionManager;
/**
* 创建订单(包含用户创建,编程式事务)
* @param userName 用户名
* @param age 年龄
* @param phone 手机号
* @param orderAmount 订单金额
* @return 订单ID
*/
public String createOrderWithUser(String userName, Integer age, String phone, BigDecimal orderAmount) {
// 1. 参数校验
if (!StringUtils.hasText(userName, "用户名不能为空")) {
thrownew IllegalArgumentException("用户名不能为空");
}
if (ObjectUtils.isEmpty(orderAmount) || orderAmount.compareTo(BigDecimal.ZERO) <= 0) {
thrownew IllegalArgumentException("订单金额必须大于0");
}
// 2. 定义事务属性:默认隔离级别、传播行为REQUIRED、非只读
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
transactionDefinition.setTimeout(30); // 超时时间30秒
// 3. 开启事务
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
try {
// 3.1 创建用户
User user = new User();
String userId = "user_" + UUID.randomUUID().toString().replace("-", "");
user.setUserId(userId);
user.setUserName(userName);
user.setAge(age);
user.setPhone(phone);
int userInsertCount = userMapper.insert(user);
log.info("创建用户,影响行数:{},用户ID:{}", userInsertCount, userId);
// 模拟异常(测试事务回滚)
// if (true) {
// throw new RuntimeException("模拟创建订单异常");
// }
// 3.2 创建订单
Order order = new Order();
String orderId = "order_" + UUID.randomUUID().toString().replace("-", "");
order.setOrderId(orderId);
order.setUserId(userId);
order.setOrderAmount(orderAmount);
order.setCreateTime(LocalDateTime.now());
int orderInsertCount = orderMapper.insert(order);
log.info("创建订单,影响行数:{},订单ID:{}", orderInsertCount, orderId);
// 4. 提交事务
transactionManager.commit(transactionStatus);
log.info("创建订单和用户成功,事务提交");
return orderId;
} catch (Exception e) {
// 5. 回滚事务
transactionManager.rollback(transactionStatus);
log.error("创建订单和用户失败,事务回滚", e);
thrownew RuntimeException("创建订单失败:" + e.getMessage());
}
}
/**
* 根据用户ID查询订单列表
* @param userId 用户ID
* @return 订单列表
*/
public List<Order> queryOrdersByUserId(String userId) {
if (!StringUtils.hasText(userId, "用户ID不能为空")) {
thrownew IllegalArgumentException("用户ID不能为空");
}
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Order::getUserId, userId);
List<Order> orderList = orderMapper.selectList(queryWrapper);
if (CollectionUtils.isEmpty(orderList)) {
log.info("用户ID:{} 暂无订单", userId);
return Lists.newArrayList();
}
return orderList;
}
}
package com.jam.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import java.util.Properties;
/**
* 数据访问层配置(数据源、事务管理器、MyBatis-Plus)
* @author ken
*/
@Configuration
@MapperScan(basePackages = "com.jam.demo.mapper") // 扫描Mapper接口
publicclass DataSourceConfig {
/**
* 配置HikariCP数据源(Spring 6.x默认)
* @return 数据源
*/
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring_demo?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");
dataSource.setUsername("root");
dataSource.setPassword("root123456");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 连接池配置
dataSource.setMaximumPoolSize(10); // 最大连接数
dataSource.setMinimumIdle(5); // 最小空闲连接数
dataSource.setIdleTimeout(300000); // 空闲连接超时时间(5分钟)
dataSource.setConnectionTimeout(30000); // 连接超时时间(30秒)
return dataSource;
}
/**
* 配置事务管理器(JDBC事务)
* @param dataSource 数据源
* @return 事务管理器
*/
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
returnnew DataSourceTransactionManager(dataSource);
}
/**
* 配置MyBatis-Plus SqlSessionFactory
* @param dataSource 数据源
* @return SqlSessionFactory
* @throws Exception 异常
*/
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
// 配置MyBatis-Plus插件(分页插件)
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
sessionFactory.setPlugins(interceptor);
// 配置MyBatis属性
Properties properties = new Properties();
properties.setProperty("mapUnderscoreToCamelCase", "true"); // 下划线转驼峰
properties.setProperty("logImpl", "SLF4J"); // 日志实现
sessionFactory.setConfigurationProperties(properties);
return sessionFactory.getObject();
}
}
package com.jam.demo.controller;
import com.jam.demo.entity.Order;
import com.jam.demo.service.OrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
/**
* 订单控制器
* @author ken
*/
@RestController
@RequestMapping("/api/order")
@Api(tags = "订单管理接口")
@RequiredArgsConstructor
@Slf4j
publicclass OrderController {
privatefinal OrderService orderService;
/**
* 创建订单(包含用户创建)
* @param userName 用户名
* @param age 年龄
* @param phone 手机号
* @param orderAmount 订单金额
* @return 订单ID
*/
@PostMapping("/create")
@ApiOperation(value = "创建订单", notes = "创建订单并自动创建关联用户,包含编程式事务")
public String createOrder(
@ApiParam(value = "用户名", required = true) @RequestParam String userName,
@ApiParam(value = "年龄") @RequestParam(required = false) Integer age,
@ApiParam(value = "手机号") @RequestParam(required = false) String phone,
@ApiParam(value = "订单金额", required = true) @RequestParam BigDecimal orderAmount
) {
return orderService.createOrderWithUser(userName, age, phone, orderAmount);
}
/**
* 根据用户ID查询订单列表
* @param userId 用户ID
* @return 订单列表
*/
@GetMapping("/list")
@ApiOperation(value = "查询订单列表", notes = "根据用户ID查询关联的订单列表")
public List<Order> queryOrderList(
@ApiParam(value = "用户ID", required = true) @RequestParam String userId
) {
return orderService.queryOrdersByUserId(userId);
}
}
package com.jam.demo;
import io.swagger.annotations.Api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.oas.annotations.EnableOpenApi;
/**
* 应用启动类
* @author ken
*/
@SpringBootApplication
@EnableOpenApi// 开启Swagger3
publicclass SpringDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDemoApplication.class, args);
System.out.println("Spring Demo应用启动成功!访问Swagger3文档:http://localhost:8080/swagger-ui/index.html");
}
}
Spring的ORM模块提供了对主流ORM框架的整合支持,通过Spring的事务管理和资源管理,简化ORM框架的使用。上面的实战示例已结合MyBatis-Plus实现了ORM操作,核心优势:
Web模块提供了Spring对Web开发的全面支持,包含Web、WebMVC、WebFlux等子模块,分别对应传统的Servlet开发、MVC开发和响应式开发。
Spring MVC是基于Servlet的MVC框架,实现了请求的接收、处理和响应的完整流程。核心组件包括:

package com.jam.demo.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
/**
* 登录校验拦截器
* @author ken
*/
@Slf4j
publicclass LoginInterceptor implements HandlerInterceptor {
/**
* 前置处理:请求执行前拦截
* @param request 请求对象
* @param response 响应对象
* @param handler 处理器
* @return true:放行;false:拦截
* @throws Exception 异常
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. 获取请求路径
String requestURI = request.getRequestURI();
log.info("登录拦截器拦截请求:{}", requestURI);
// 2. 放行登录接口
if (requestURI.contains("/api/login")) {
log.info("登录接口,直接放行");
returntrue;
}
// 3. 校验登录状态(从Session获取用户信息)
HttpSession session = request.getSession();
Object user = session.getAttribute("loginUser");
if (!StringUtils.isEmpty(user)) {
log.info("用户已登录,放行请求");
returntrue;
}
// 4. 未登录,返回401未授权
log.info("用户未登录,拦截请求");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("{\"code\":401,\"msg\":\"未登录,请先登录\"}");
returnfalse;
}
/**
* 后置处理:处理器方法执行后,视图渲染前
* @param request 请求对象
* @param response 响应对象
* @param handler 处理器
* @param modelAndView 模型和视图
* @throws Exception 异常
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("登录拦截器后置处理");
}
/**
* 完成处理:视图渲染后,请求完成
* @param request 请求对象
* @param response 响应对象
* @param handler 处理器
* @param ex 异常对象
* @throws Exception 异常
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("登录拦截器完成处理");
}
}
package com.jam.demo.config;
import com.jam.demo.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web MVC配置类,注册拦截器
* @author ken
*/
@Configuration
publicclass WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册登录拦截器,拦截所有/api/**路径的请求
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login"); // 放行登录接口
}
}
package com.jam.demo.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpSession;
/**
* 登录控制器
* @author ken
*/
@RestController
@RequestMapping("/api")
@Api(tags = "登录管理接口")
@Slf4j
publicclass LoginController {
/**
* 登录接口
* @param username 用户名
* @param password 密码
* @param session Session对象
* @return 登录结果
*/
@PostMapping("/login")
@ApiOperation(value = "用户登录", notes = "用户登录并将用户信息存入Session")
public String login(
@ApiParam(value = "用户名", required = true) @RequestParam String username,
@ApiParam(value = "密码", required = true) @RequestParam String password,
HttpSession session
) {
// 简单校验(实际开发中需查询数据库)
if (!StringUtils.hasText(username, "用户名不能为空") || !StringUtils.hasText(password, "密码不能为空")) {
return"{\"code\":400,\"msg\":\"用户名或密码不能为空\"}";
}
if ("admin".equals(username) && "admin123".equals(password)) {
// 登录成功,存入Session
session.setAttribute("loginUser", username);
log.info("用户{}登录成功", username);
return"{\"code\":200,\"msg\":\"登录成功\"}";
}
log.info("用户{}登录失败,用户名或密码错误", username);
return"{\"code\":401,\"msg\":\"用户名或密码错误\"}";
}
}
特性 | BeanFactory | ApplicationContext |
|---|---|---|
加载方式 | 懒加载(默认),获取Bean时才创建 | 非懒加载(默认),启动时创建单例Bean |
功能范围 | 核心Bean管理功能 | 包含BeanFactory所有功能,新增国际化、事件发布、资源访问等 |
适用场景 | 资源紧张的环境(如移动端) | 企业级应用(绝大多数场景) |
实现类 | DefaultListableBeanFactory | AnnotationConfigApplicationContext、ClassPathXmlApplicationContext等 |
特性 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
实现原理 | 基于接口,生成接口的代理类 | 基于继承,生成目标类的子类 |
目标对象要求 | 必须实现接口 | 无需实现接口(但不能是final类/方法) |
创建效率 | 较快(直接生成接口代理类字节码) | 较慢(需通过ASM框架修改字节码) |
执行效率 | 较慢(反射调用目标方法) | 较快(直接调用子类方法,无反射) |
内存占用 | 较少 | 较多(生成的子类字节码更复杂) |
Spring 中的使用场景 | 目标对象实现接口时默认使用 | 目标对象无接口时自动使用;可通过proxyTargetClass=true强制使用 |
java.lang.reflect.Proxy和InvocationHandler,CGLIB依赖ASM字节码操作框架;package com.jam.demo.proxy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK 动态代理示例(基于接口)
* @author ken
*/
@Slf4j
publicclass JdkProxyDemo {
// 目标接口
publicinterface UserDao {
/**
* 保存用户
* @param userName 用户名
* @return 保存结果
*/
boolean saveUser(String userName);
}
// 目标对象(实现接口)
publicstaticclass UserDaoImpl implements UserDao {
@Override
public boolean saveUser(String userName) {
if (!org.springframework.util.StringUtils.hasText(userName)) {
log.error("用户名不能为空");
returnfalse;
}
log.info("JDK动态代理-保存用户:{}", userName);
returntrue;
}
}
// JDK动态代理处理器
publicstaticclass JdkProxyHandler implements InvocationHandler {
// 目标对象
privatefinal Object target;
public JdkProxyHandler(Object target) {
this.target = target;
}
/**
* 代理方法执行逻辑
* @param proxy 代理对象
* @param method 目标方法
* @param args 方法参数
* @return 方法返回值
* @throws Throwable 异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强:日志输出
log.info("【JDK代理-前置】执行方法:{},参数:{}", method.getName(), args);
// 执行目标方法
Object result = method.invoke(target, args);
// 后置增强:结果输出
log.info("【JDK代理-后置】方法执行完成,返回值:{}", result);
return result;
}
}
// 测试方法
public static void main(String[] args) {
// 1. 创建目标对象
UserDao target = new UserDaoImpl();
// 2. 创建JDK动态代理对象
UserDao proxy = (UserDao) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JdkProxyHandler(target)
);
// 3. 调用代理方法
proxy.saveUser("张三");
// 验证代理对象类型
log.info("代理对象类型:{}", proxy.getClass().getName());
log.info("是否为目标对象实例:{}", proxy instanceof UserDaoImpl);
}
}
package com.jam.demo.proxy;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
/**
* CGLIB 动态代理示例(基于继承)
* @author ken
*/
@Slf4j
publicclass CglibProxyDemo {
// 目标对象(无需实现接口)
publicstaticclass OrderDao {
/**
* 创建订单
* @param orderId 订单ID
* @return 创建结果
*/
public boolean createOrder(String orderId) {
if (!StringUtils.hasText(orderId)) {
log.error("订单ID不能为空");
returnfalse;
}
log.info("CGLIB动态代理-创建订单:{}", orderId);
returntrue;
}
}
// CGLIB方法拦截器
publicstaticclass CglibProxyInterceptor implements MethodInterceptor {
/**
* 拦截目标方法,执行增强逻辑
* @param obj 代理对象(目标类的子类)
* @param method 目标方法
* @param args 方法参数
* @param proxy 方法代理对象(用于调用目标方法)
* @return 方法返回值
* @throws Throwable 异常
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 前置增强:日志输出
log.info("【CGLIB代理-前置】执行方法:{},参数:{}", method.getName(), args);
// 执行目标方法(使用proxy.invokeSuper避免递归调用)
Object result = proxy.invokeSuper(obj, args);
// 后置增强:结果输出
log.info("【CGLIB代理-后置】方法执行完成,返回值:{}", result);
return result;
}
}
// 测试方法
public static void main(String[] args) {
// 1. 创建CGLIB增强器
Enhancer enhancer = new Enhancer();
// 2. 设置父类(目标类)
enhancer.setSuperclass(OrderDao.class);
// 3. 设置方法拦截器
enhancer.setCallback(new CglibProxyInterceptor());
// 4. 创建代理对象(目标类的子类)
OrderDao proxy = (OrderDao) enhancer.create();
// 5. 调用代理方法
proxy.createOrder("order_1001");
// 验证代理对象类型
log.info("代理对象类型:{}", proxy.getClass().getName());
log.info("是否为目标对象实例:{}", proxy instanceof OrderDao);
}
}
<!-- CGLIB 依赖(Spring AOP已包含,单独使用时需引入) -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
特性 | 声明式事务(@Transactional) | 编程式事务(PlatformTransactionManager) |
|---|---|---|
实现方式 | 基于AOP,注解驱动 | 手动编码调用事务API |
代码侵入性 | 低(仅需添加注解) | 高(业务代码中嵌入事务逻辑) |
灵活性 | 较低(依赖注解属性配置) | 较高(可灵活控制事务边界、异常处理) |
配置复杂度 | 低(注解+少量配置) | 高(需手动管理事务开启、提交、回滚) |
适用场景 | 简单事务场景(单方法、固定事务属性) | 复杂事务场景(多方法组合、动态事务属性) |
异常处理 | 默认仅回滚RuntimeException及其子类 | 可自定义回滚异常类型 |
package com.jam.demo.transaction;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jam.demo.entity.User;
import com.jam.demo.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
/**
* 声明式事务示例
* @author ken
*/
@Service
@Slf4j
@RequiredArgsConstructor
publicclass DeclarativeTransactionService {
privatefinal UserMapper userMapper;
/**
* 声明式事务:修改用户信息
* 事务属性:默认传播行为REQUIRED,默认回滚RuntimeException
* @param userId 用户ID
* @param newUserName 新用户名
*/
@Transactional(rollbackFor = Exception.class) // 指定所有异常都回滚
public void updateUserName(String userId, String newUserName) {
// 参数校验
if (!StringUtils.hasText(userId, "用户ID不能为空") || !StringUtils.hasText(newUserName, "新用户名不能为空")) {
thrownew IllegalArgumentException("用户ID或新用户名不能为空");
}
// 1. 查询用户
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUserId, userId);
User user = userMapper.selectOne(queryWrapper);
if (user == null) {
thrownew RuntimeException("用户不存在,用户ID:" + userId);
}
// 2. 修改用户名
user.setUserName(newUserName);
userMapper.updateById(user);
log.info("修改用户{}的用户名为:{}", userId, newUserName);
// 模拟异常(测试事务回滚)
// if (true) {
// throw new RuntimeException("模拟修改用户信息异常");
// }
}
}
特性 | Spring AOP | AspectJ |
|---|---|---|
实现方式 | 动态代理(JDK/CGLIB),运行时增强 | 字节码织入,编译期/类加载期增强 |
增强时机 | 运行时(程序运行时动态生成代理对象) | 编译期(.java→.class时织入)/类加载期(.class加载到JVM时织入) |
功能范围 | 仅支持方法级别的增强 | 支持方法、字段、构造函数等多种增强点 |
代码侵入性 | 低(无需修改目标类代码) | 编译期织入无侵入,加载期织入需修改类加载器 |
性能 | 运行时增强有一定性能开销 | 编译期织入无运行时开销,性能更优 |
集成复杂度 | 低(Spring框架内置支持) | 高(需引入AspectJ编译器、配置织入) |
适用场景 | 绝大多数企业级应用的方法增强场景 | 需字段/构造函数增强、对性能要求极高的场景 |
Spring 体系结构的核心是“分层设计+模块化拆分”,围绕“IOC容器”和“AOP”两大核心思想,构建了覆盖核心容器、数据访问、Web开发、测试等全链路的生态体系。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version><!-- Spring Boot最新稳定版本,对应Spring 6.1.5 -->
<relativePath/>
</parent>
<groupId>com.jam.demo</groupId>
<artifactId>spring-system-demo</artifactId>
<version>1.0.0</version>
<name>spring-system-demo</name>
<description>Spring体系结构实战演示项目</description>
<properties>
<java.version>17</java.version>
<lombok.version>1.18.30</lombok.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<fastjson2.version>2.0.45</fastjson2.version>
<guava.version>33.2.1-jre</guava.version>
<swagger.version>3.0.0</swagger.version>
<cglib.version>3.3.0</cglib.version>
</properties>
<dependencies>
<!-- Spring Boot核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Web依赖(Spring MVC) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AOP依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Spring 事务依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- FastJSON2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson2.version}</version>
</dependency>
<!-- Google Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- Swagger3 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- CGLIB -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>${cglib.version}</version>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<!-- Java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
Spring 体系结构并非孤立的模块堆砌,而是以“IOC容器”为核心、以“AOP”为扩展手段,层层递进、相互支撑的完整生态。理解Spring体系结构,关键在于抓住“IOC解耦”和“AOP复用”两大核心思想,明确各模块的定位和依赖关系。