Spring入门教程 - 从零开始学习Spring框架
Spring入门教程 - 从零开始学习Spring框架
Spring框架是Java企业级应用开发最流行的框架之一。本教程将带你从零开始,系统学习Spring框架的核心概念和实际应用,通过详细的代码示例和实战项目,让你快速掌握Spring开发技能。
📚 目录
- Spring框架简介
- 环境搭建
- 第一个Spring程序
- IoC容器和依赖注入
- Bean管理
- AOP面向切面编程
- Spring事务管理
- Spring MVC
- Spring Boot快速入门
- 实战项目
- 常见问题解答
- 学习资源推荐
1. Spring框架简介
Spring框架是由Rod Johnson在2003年创建的一个开源Java企业级应用开发框架。Spring的核心目标是简化Java企业级应用的开发,通过提供全面的基础设施支持,让开发者专注于业务逻辑的实现。
Spring框架的核心特性包括:
传统方式:对象自己创建和管理依赖
Spring方式:由Spring容器负责对象的创建和依赖管理
优势:降低代码耦合度,提高可测试性和可维护性
概念:通过构造函数、setter方法或字段注入依赖对象
方式:构造器注入、setter注入、字段注入
好处:实现松耦合,便于单元测试
作用:将横切关注点(如日志、事务、安全)从业务逻辑中分离
应用场景:日志记录、性能监控、事务管理、安全检查等
- 轻量级:Spring框架本身不依赖其他框架,可以独立使用
- 非侵入式:应用代码对Spring框架的依赖最小化
- 容器管理:Spring容器管理对象的生命周期和依赖关系
- 声明式编程:通过配置实现功能,减少样板代码
- 易于测试:支持依赖注入,便于编写单元测试
- 丰富的生态:Spring Boot、Spring Cloud等扩展框架
Spring框架由多个模块组成:
Spring Core Container(核心容器)
├── spring-core:核心工具类
├── spring-beans:Bean工厂和依赖注入
├── spring-context:应用上下文
└── spring-expression:SpEL表达式语言
AOP and Instrumentation(AOP和工具)
├── spring-aop:面向切面编程
├── spring-aspects:AspectJ集成
└── spring-instrument:类加载器实现
Data Access/Integration(数据访问/集成)
├── spring-jdbc:JDBC支持
├── spring-orm:ORM框架支持
├── spring-oxm:对象XML映射
├── spring-jms:Java消息服务
└── spring-tx:事务管理
Web(Web层)
├── spring-web:Web基础功能
├── spring-webmvc:Spring MVC
├── spring-websocket:WebSocket支持
└── spring-webmvc-portlet:Portlet支持
Test(测试)
└── spring-test:测试支持- Spring 1.x (2004-2006):初始版本
- Spring 2.x (2006-2009):引入注解支持
- Spring 3.x (2009-2013):Java配置、REST支持
- Spring 4.x (2013-2017):Java 8支持、WebSocket
- Spring 5.x (2017-至今):响应式编程、Kotlin支持
- Spring 6.x (2022-至今):Java 17+、Jakarta EE
2. 环境搭建
在开始学习Spring之前,你需要:
- ✅ JDK 8或更高版本(推荐JDK 11或JDK 17)
- ✅ Maven或Gradle(构建工具)
- ✅ IDE(IntelliJ IDEA、Eclipse或VS Code)
IntelliJ IDEA:
- File → New → Project
- 选择Maven
- 填写GroupId和ArtifactId
- 点击Finish
Eclipse:
- File → New → Maven Project
- 选择maven-archetype-quickstart
- 填写GroupId和ArtifactId
- 点击Finish
创建项目目录结构:
spring-tutorial/
├── pom.xml
└── src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── App.java
│ └── resources/
│ └── applicationContext.xml
└── test/
└── java/2.3 添加Spring依赖
编辑pom.xml文件,添加Spring核心依赖:
<?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>
<groupId>com.example</groupId>
<artifactId>spring-tutorial</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>5.3.23</spring.version>
</properties>
<dependencies>
<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- AspectJ Weaver (AOP需要) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<!-- JUnit 5 (测试) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
<!-- Spring Test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>创建测试类验证Spring是否配置成功:
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
System.out.println("Spring环境配置成功!");
}
}运行程序,如果能够正常编译和运行,说明环境配置成功。
3. 第一个Spring程序
首先创建一个简单的Java类:
package com.example.service;
public class HelloService {
private String message;
public HelloService() {
this.message = "Hello, Spring!";
}
public HelloService(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void sayHello() {
System.out.println(message);
}
}在src/main/resources目录下创建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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义HelloService Bean -->
<bean id="helloService" class="com.example.service.HelloService">
<property name="message" value="Hello, Spring Framework!"/>
</bean>
</beans>3.3 使用Spring容器
创建主类使用Spring容器:
package com.example;
import com.example.service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 加载Spring配置文件,创建Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 从容器中获取Bean
HelloService helloService = context.getBean("helloService", HelloService.class);
// 3. 使用Bean
helloService.sayHello();
// 4. 关闭容器
((ClassPathXmlApplicationContext) context).close();
}
}运行App类的main方法,输出结果:
Hello, Spring Framework!恭喜! 你已经成功创建了第一个Spring程序!
- ApplicationContext:Spring容器的接口,负责管理Bean
- ClassPathXmlApplicationContext:从类路径加载XML配置文件的实现类
- Bean:Spring管理的对象,通过配置文件定义
- 依赖注入:通过
<property>标签注入属性值
4. IoC容器和依赖注入
**控制反转(Inversion of Control)**是Spring框架的核心思想。
传统方式(紧耦合)
// 传统方式:对象自己创建依赖
public class UserService {
private UserDao userDao = new UserDaoImpl(); // 紧耦合
public void saveUser(User user) {
userDao.save(user);
}
}问题:
- 代码耦合度高
- 难以测试(无法mock依赖)
- 难以替换实现
Spring方式(松耦合)
// Spring方式:依赖由容器注入
public class UserService {
private UserDao userDao; // 依赖注入
// 构造器注入
public UserService(UserDao userDao) {
this.userDao = userDao;
}
public void saveUser(User user) {
userDao.save(user);
}
}优势:
- 代码解耦
- 易于测试
- 易于替换实现
优点:强制依赖,不可变,适合必需依赖
public class UserService {
private final UserDao userDao;
private final EmailService emailService;
// 构造器注入
public UserService(UserDao userDao, EmailService emailService) {
this.userDao = userDao;
this.emailService = emailService;
}
}XML配置:
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>
<bean id="emailService" class="com.example.service.EmailServiceImpl"/>
<bean id="userService" class="com.example.service.UserService">
<constructor-arg ref="userDao"/>
<constructor-arg ref="emailService"/>
</bean>Java配置:
@Configuration
public class AppConfig {
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
@Bean
public UserService userService(UserDao userDao, EmailService emailService) {
return new UserService(userDao, emailService);
}
}优点:可选依赖,灵活
public class UserService {
private UserDao userDao;
private EmailService emailService;
// Setter注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}XML配置:
<bean id="userService" class="com.example.service.UserService">
<property name="userDao" ref="userDao"/>
<property name="emailService" ref="emailService"/>
</bean>缺点:难以测试,隐藏依赖关系
@Service
public class UserService {
@Autowired
private UserDao userDao; // 字段注入(不推荐)
}完整示例
1. 创建接口和实现类:
// UserDao接口
package com.example.dao;
public interface UserDao {
void save(User user);
User findById(Long id);
}
// UserDaoImpl实现
package com.example.dao;
public class UserDaoImpl implements UserDao {
@Override
public void save(User user) {
System.out.println("保存用户: " + user.getName());
}
@Override
public User findById(Long id) {
return new User(id, "张三");
}
}
// EmailService接口
package com.example.service;
public interface EmailService {
void sendEmail(String to, String subject, String content);
}
// EmailServiceImpl实现
package com.example.service;
public class EmailServiceImpl implements EmailService {
@Override
public void sendEmail(String to, String subject, String content) {
System.out.println("发送邮件到: " + to);
System.out.println("主题: " + subject);
System.out.println("内容: " + content);
}
}2. 创建User实体类:
package com.example.model;
public class User {
private Long id;
private String name;
private String email;
public User() {}
public User(Long id, String name) {
this.id = id;
this.name = name;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}3. 创建UserService:
package com.example.service;
import com.example.dao.UserDao;
import com.example.model.User;
public class UserService {
private final UserDao userDao;
private final EmailService emailService;
public UserService(UserDao userDao, EmailService emailService) {
this.userDao = userDao;
this.emailService = emailService;
}
public void registerUser(User user) {
// 保存用户
userDao.save(user);
// 发送欢迎邮件
emailService.sendEmail(user.getEmail(), "欢迎", "欢迎注册!");
}
}4. 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义Bean -->
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>
<bean id="emailService" class="com.example.service.EmailServiceImpl"/>
<bean id="userService" class="com.example.service.UserService">
<constructor-arg ref="userDao"/>
<constructor-arg ref="emailService"/>
</bean>
</beans>5. 使用:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
User user = new User(1L, "张三");
user.setEmail("zhangsan@example.com");
userService.registerUser(user);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"
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">
<!-- 启用注解支持 -->
<context:component-scan base-package="com.example"/>
<context:annotation-config/>
</beans>@Component:通用组件注解
@Component
public class UserDaoImpl implements UserDao {
// ...
}@Service:服务层注解
@Service
public class UserService {
// ...
}@Repository:数据访问层注解
@Repository
public class UserDaoImpl implements UserDao {
// ...
}@Controller:控制器注解
@Controller
public class UserController {
// ...
}@Autowired:自动装配
@Service
public class UserService {
private final UserDao userDao;
private final EmailService emailService;
// 构造器注入(推荐)
@Autowired
public UserService(UserDao userDao, EmailService emailService) {
this.userDao = userDao;
this.emailService = emailService;
}
}@Qualifier:指定Bean名称
@Service
public class UserService {
@Autowired
@Qualifier("userDaoImpl")
private UserDao userDao;
}@Value:注入值
@Service
public class ConfigService {
@Value("${app.name}")
private String appName;
@Value("100")
private int maxUsers;
}使用@Configuration和@Bean注解进行Java配置:
package com.example.config;
import com.example.dao.UserDao;
import com.example.dao.UserDaoImpl;
import com.example.service.EmailService;
import com.example.service.EmailServiceImpl;
import com.example.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
@Bean
public EmailService emailService() {
return new EmailServiceImpl();
}
@Bean
public UserService userService(UserDao userDao, EmailService emailService) {
return new UserService(userDao, emailService);
}
}使用Java配置:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean("userService", UserService.class);5. Bean管理
Spring支持以下Bean作用域:
| 作用域 | 说明 | 使用场景 |
|---|---|---|
| singleton | 单例(默认) | 无状态Bean,如Service、Dao |
| prototype | 多例 | 有状态Bean,每次获取新实例 |
| request | 请求作用域 | Web应用,每个HTTP请求一个实例 |
| session | 会话作用域 | Web应用,每个HTTP会话一个实例 |
| application | 应用作用域 | Web应用,整个应用一个实例 |
| websocket | WebSocket作用域 | WebSocket连接作用域 |
XML配置:
<!-- 单例(默认) -->
<bean id="userService" class="com.example.service.UserService" scope="singleton"/>
<!-- 多例 -->
<bean id="userService" class="com.example.service.UserService" scope="prototype"/>注解配置:
@Service
@Scope("singleton") // 或 @Scope("prototype")
public class UserService {
// ...
}Bean的生命周期包括以下阶段:
- 实例化:创建Bean实例
- 属性赋值:注入依赖
- 初始化:调用初始化方法
- 使用:Bean可用
- 销毁:调用销毁方法
实现InitializingBean和DisposableBean接口:
@Service
public class UserService implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("UserService初始化");
}
@Override
public void destroy() throws Exception {
System.out.println("UserService销毁");
}
}使用@PostConstruct和@PreDestroy注解:
@Service
public class UserService {
@PostConstruct
public void init() {
System.out.println("UserService初始化");
}
@PreDestroy
public void cleanup() {
System.out.println("UserService销毁");
}
}XML配置:
<bean id="userService" class="com.example.service.UserService"
init-method="init" destroy-method="cleanup"/>Spring支持以下自动装配模式:
- no:不自动装配(默认)
- byName:按名称自动装配
- byType:按类型自动装配
- constructor:构造器自动装配
XML配置:
<bean id="userService" class="com.example.service.UserService" autowire="byType"/>注解方式(推荐):
@Service
public class UserService {
@Autowired // 按类型自动装配
private UserDao userDao;
}使用@Conditional注解实现条件化Bean:
@Configuration
public class AppConfig {
@Bean
@ConditionalOnProperty(name = "db.type", havingValue = "mysql")
public DataSource mysqlDataSource() {
return new MysqlDataSource();
}
@Bean
@ConditionalOnProperty(name = "db.type", havingValue = "postgresql")
public DataSource postgresqlDataSource() {
return new PostgresqlDataSource();
}
}6. AOP面向切面编程
**AOP(Aspect-Oriented Programming)**面向切面编程,用于将横切关注点从业务逻辑中分离出来。
横切关注点示例:
日志记录
性能监控
事务管理
安全检查
异常处理
Aspect(切面):横切关注点的模块化
Join Point(连接点):程序执行的某个特定位置
Pointcut(切点):匹配连接点的表达式
Advice(通知):在切点上执行的动作
Target(目标对象):被代理的对象
Proxy(代理):AOP框架创建的对象
Weaving(织入):将切面应用到目标对象的过程
- @Before:前置通知,方法执行前
- @After:后置通知,方法执行后(无论成功或失败)
- @AfterReturning:返回通知,方法正常返回后
- @AfterThrowing:异常通知,方法抛出异常后
- @Around:环绕通知,方法执行前后
package com.example.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
// 定义切点:匹配com.example.service包下所有类的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
// 前置通知
@Before("serviceMethods()")
public void logBefore(JoinPoint joinPoint) {
System.out.println("方法执行前: " + joinPoint.getSignature().getName());
}
// 后置通知
@After("serviceMethods()")
public void logAfter(JoinPoint joinPoint) {
System.out.println("方法执行后: " + joinPoint.getSignature().getName());
}
// 返回通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("方法返回: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "exception")
public void logAfterThrowing(JoinPoint joinPoint, Exception exception) {
System.out.println("方法抛出异常: " + exception.getMessage());
}
// 环绕通知
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("方法开始执行: " + joinPoint.getSignature().getName());
try {
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println("方法执行完成,耗时: " + (end - start) + "ms");
return result;
} catch (Exception e) {
System.out.println("方法执行异常: " + e.getMessage());
throw e;
}
}
}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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example"/>
<aop:aspectj-autoproxy/>
</beans>Java配置:
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.example")
public class AppConfig {
}@Service
public class UserService {
public void saveUser(User user) {
System.out.println("保存用户: " + user.getName());
}
public User findUser(Long id) {
return new User(id, "张三");
}
}运行测试:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean("userService", UserService.class);
User user = new User(1L, "张三");
userService.saveUser(user);输出:
方法开始执行: saveUser
方法执行前: saveUser
保存用户: 张三
方法执行后: saveUser
方法返回: null
方法执行完成,耗时: Xmsexecution表达式语法:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)示例:
// 匹配所有public方法
@Pointcut("execution(public * *(..))")
// 匹配所有以save开头的方法
@Pointcut("execution(* save*(..))")
// 匹配com.example.service包下所有类的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
// 匹配UserService类的所有方法
@Pointcut("execution(* com.example.service.UserService.*(..))")
// 匹配返回User类型的方法
@Pointcut("execution(User com.example.service.*.*(..))")
// 匹配只有一个String参数的方法
@Pointcut("execution(* com.example.service.*.*(String))")7. Spring事务管理
**事务(Transaction)**是一组操作的执行单元,要么全部成功,要么全部失败。
ACID特性:
- Atomicity(原子性):事务不可分割
- Consistency(一致性):数据保持一致
- Isolation(隔离性):事务之间相互隔离
- Durability(持久性):事务提交后数据持久化
Spring提供了声明式事务管理,通过@Transactional注解实现。
XML配置:
<!-- 数据源 -->
<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/test"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>Java配置:
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
// 方法级别事务
@Transactional(rollbackFor = Exception.class)
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
// 扣款
userDao.deduct(fromId, amount);
// 如果这里抛出异常,上面的操作会回滚
userDao.add(toId, amount);
}
// 只读事务
@Transactional(readOnly = true)
public User findUser(Long id) {
return userDao.findById(id);
}
// 指定事务传播行为
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(User user) {
userDao.save(user);
}
}| 传播行为 | 说明 |
|---|---|
| REQUIRED | 如果当前存在事务,则加入;否则创建新事务(默认) |
| REQUIRES_NEW | 创建新事务,如果当前存在事务则挂起 |
| SUPPORTS | 如果当前存在事务,则加入;否则以非事务方式执行 |
| NOT_SUPPORTED | 以非事务方式执行,如果当前存在事务则挂起 |
| MANDATORY | 如果当前存在事务,则加入;否则抛出异常 |
| NEVER | 以非事务方式执行,如果当前存在事务则抛出异常 |
| NESTED | 如果当前存在事务,则创建嵌套事务 |
| 隔离级别 | 说明 |
|---|---|
| READ_UNCOMMITTED | 读未提交(最低) |
| READ_COMMITTED | 读已提交 |
| REPEATABLE_READ | 可重复读 |
| SERIALIZABLE | 串行化(最高) |
@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateUser(User user) {
userDao.update(user);
}8. Spring MVC
Spring MVC是Spring框架的Web模块,用于构建Web应用程序。
MVC模式:
- Model(模型):数据和业务逻辑
- View(视图):用户界面
- Controller(控制器):处理用户请求
- 用户发送请求到DispatcherServlet
- DispatcherServlet查询HandlerMapping找到对应的Controller
- Controller处理请求,返回ModelAndView
- DispatcherServlet查询ViewResolver找到对应的View
- View渲染后返回给用户
<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- JSP支持 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies><?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>package com.example.controller;
import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
// GET /users
@GetMapping
public String listUsers(Model model) {
model.addAttribute("users", userService.findAll());
return "user/list";
}
// GET /users/{id}
@GetMapping("/{id}")
public String getUser(@PathVariable Long id, Model model) {
User user = userService.findById(id);
model.addAttribute("user", user);
return "user/detail";
}
// POST /users
@PostMapping
public String createUser(@ModelAttribute User user) {
userService.save(user);
return "redirect:/users";
}
// RESTful API
@GetMapping("/api/{id}")
@ResponseBody
public User getUserApi(@PathVariable Long id) {
return userService.findById(id);
}
}- @Controller:标识控制器
- @RestController:REST控制器(@Controller + @ResponseBody)
- @RequestMapping:映射请求URL
- @GetMapping:GET请求映射
- @PostMapping:POST请求映射
- @PutMapping:PUT请求映射
- @DeleteMapping:DELETE请求映射
- @PathVariable:路径变量
- @RequestParam:请求参数
- @RequestBody:请求体
- @ResponseBody:响应体
- @ModelAttribute:模型属性
9. Spring Boot快速入门
Spring Boot是Spring框架的扩展,简化了Spring应用的开发和部署。
特点:
- 自动配置
- 内嵌服务器(Tomcat、Jetty)
- 无需XML配置
- 生产就绪特性
使用Spring Initializr
访问 https://start.spring.io/ 创建项目,或使用IDE创建。
手动创建
pom.xml:
<?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>2.7.8</version>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-boot-tutorial</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>主类:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}Controller:
package com.example.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}运行Application类的main方法,访问 http://localhost:8080/hello
application.properties:
server.port=8080
spring.application.name=spring-boot-tutorialapplication.yml:
server:
port: 8080
spring:
application:
name: spring-boot-tutorial10. 实战项目
创建一个完整的用户管理系统,包含:
- 用户注册
- 用户登录
- 用户列表
- 用户详情
- 用户更新
- 用户删除
项目结构:
user-management/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ ├── UserManagementApplication.java
│ │ │ ├── controller/
│ │ │ │ └── UserController.java
│ │ │ ├── service/
│ │ │ │ └── UserService.java
│ │ │ ├── dao/
│ │ │ │ └── UserDao.java
│ │ │ └── model/
│ │ │ └── User.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
└── pom.xml核心代码示例:
// User.java
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
private String password;
// getters and setters
}
// UserService.java
@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
public User save(User user) {
return userDao.save(user);
}
public List<User> findAll() {
return userDao.findAll();
}
public User findById(Long id) {
return userDao.findById(id).orElseThrow();
}
public void delete(Long id) {
userDao.deleteById(id);
}
}
// UserController.java
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> list() {
return userService.findAll();
}
@PostMapping
public User create(@RequestBody User user) {
return userService.save(user);
}
@GetMapping("/{id}")
public User get(@PathVariable Long id) {
return userService.findById(id);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
userService.delete(id);
}
}11. 常见问题解答
Q1: Spring和Spring Boot有什么区别?
A: Spring是一个框架,需要大量XML配置;Spring Boot是Spring的扩展,提供自动配置,简化开发。
Q2: @Autowired和@Resource有什么区别?
A:
@Autowired:Spring注解,按类型注入@Resource:JSR-250注解,按名称注入
Q3: Bean的作用域有哪些?
A: singleton(默认)、prototype、request、session、application、websocket
Q4: 如何解决循环依赖?
A:
- 使用
@Lazy延迟加载 - 使用setter注入代替构造器注入
- 重构代码,消除循环依赖
Q5: Spring MVC和Spring Boot MVC有什么区别?
A: Spring Boot MVC是Spring MVC的自动配置版本,减少了配置工作。
12. 学习资源推荐
官方资源
- Spring官方文档:https://spring.io/projects/spring-framework
- Spring Boot官方文档:https://spring.io/projects/spring-boot
- Spring Guides:https://spring.io/guides
推荐书籍
- 《Spring实战》(Spring in Action)
- 《Spring Boot实战》
- 《深入理解Spring MVC源代码》
在线课程
- Spring官方教程
- 慕课网Spring课程
- B站Spring教程
实践建议
- 多写代码:理论结合实践
- 阅读源码:深入理解Spring原理
- 做项目:通过实际项目巩固知识
- 参与开源:贡献Spring相关项目
总结
通过本教程,你已经学习了:
✅ Spring框架的核心概念(IoC、DI、AOP)
✅ Spring Bean管理和依赖注入
✅ Spring AOP面向切面编程
✅ Spring事务管理
✅ Spring MVC Web开发
✅ Spring Boot快速开发
下一步学习方向:
- 深入学习Spring Boot高级特性
- 学习Spring Cloud微服务
- 学习Spring Data JPA
- 学习Spring Security安全框架
- 阅读Spring源码,深入理解原理
记住:Spring是一个强大的框架,需要持续学习和实践。多写代码,多做项目,才能真正掌握Spring开发技能。
本教程持续更新中,如有问题欢迎反馈。祝你学习愉快! 🚀
相关关键词: Spring入门, Spring教程, Spring框架, Spring IoC, Spring DI, Spring AOP, Spring MVC, Spring Boot, Java Spring, Spring学习, Spring实战, Spring从零开始