学习时间: 4-5小时
学习目标: 初步了解Spring框架,掌握依赖注入(DI)和控制反转(IoC)核心概念
📋 详细学习清单
✅ 第一部分:Spring框架概念理解(90分钟)
1. Spring框架与前端框架对比
Vue.js (你熟悉的前端框架)
javascript
// Vue.js 组件化开发
// main.js - 应用入口
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App)
app.use(store) // 使用状态管理
app.use(router) // 使用路由
app.mount('#app')
// 组件依赖注入
// UserService.js
export class UserService {
async getUsers() {
return await fetch('/api/users').then(res => res.json())
}
}
// UserComponent.vue
import { UserService } from '@/services/UserService'
export default {
data() {
return {
users: [],
userService: new UserService() // 手动创建依赖
}
},
async mounted() {
this.users = await this.userService.getUsers()
}
}
Spring框架 (今天学习的后端框架)
java
// Spring应用程序入口
// Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 服务层 - Spring自动管理
@Service // 标记为Spring管理的组件
public class UserService {
@Autowired // 自动注入依赖
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User createUser(User user) {
return userRepository.save(user);
}
}
// 控制器层 - Spring自动注入
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired // Spring自动注入UserService
private UserService userService;
@GetMapping
public List<User> getUsers() {
return userService.getAllUsers(); // 不需要手动创建service实例
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
}
2. 核心概念详解
IoC(控制反转)概念
java
// 传统方式 - 手动控制依赖
public class UserController {
private UserService userService;
public UserController() {
// 自己创建依赖 - 紧耦合
this.userService = new UserService();
}
}
// Spring IoC方式 - 框架控制依赖
@RestController
public class UserController {
@Autowired // 交给Spring容器管理
private UserService userService;
// Spring会自动注入userService实例
// 我们不需要知道如何创建,只需要使用
}
DI(依赖注入)三种方式
java
// 1. 构造函数注入(推荐)
@RestController
public class UserController {
private final UserService userService;
// 构造函数注入 - 保证依赖不为null
public UserController(UserService userService) {
this.userService = userService;
}
}
// 2. Setter方法注入
@RestController
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
// 3. 字段注入(简单但不推荐)
@RestController
public class UserController {
@Autowired
private UserService userService;
}
✅ 第二部分:Spring Bean管理(80分钟)
1. Bean的概念和生命周期
什么是Bean?
java
// Bean就是由Spring容器管理的对象
// 类似于Vue中由Vue实例管理的组件
// 1. 使用注解标记Bean
@Component // 通用组件
public class EmailService {
public void sendEmail(String to, String message) {
System.out.println("发送邮件给: " + to);
}
}
@Service // 业务逻辑层
public class UserService {
// ...
}
@Repository // 数据访问层
public class UserRepository {
// ...
}
@Controller // 控制器层
public class UserController {
// ...
}
// 2. 使用@Configuration和@Bean
@Configuration
public class AppConfig {
@Bean
public EmailService emailService() {
return new EmailService();
}
@Bean
public UserService userService() {
return new UserService();
}
}
2. Bean的作用域
java
// 单例模式(默认)- 类似于Vue的全局状态
@Service
@Scope("singleton") // 整个应用只有一个实例
public class UserService {
private int counter = 0;
public void incrementCounter() {
counter++;
System.out.println("计数器: " + counter);
}
}
// 原型模式 - 每次注入都创建新实例
@Service
@Scope("prototype") // 每次请求都创建新实例
public class TaskService {
private String taskId = UUID.randomUUID().toString();
public String getTaskId() {
return taskId;
}
}
// Web相关作用域
@Service
@Scope("request") // 每个HTTP请求一个实例
public class RequestService {
// ...
}
@Service
@Scope("session") // 每个用户会话一个实例
public class SessionService {
// ...
}
✅ 第三部分:Spring配置方式(70分钟)
1. 基于注解的配置(推荐)
java
// 1. 应用程序主配置
@SpringBootApplication // 包含@Configuration + @EnableAutoConfiguration + @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 2. 组件扫描
@ComponentScan(basePackages = {"com.example.service", "com.example.controller"})
@Configuration
public class AppConfig {
// Spring会自动扫描指定包下的@Component, @Service, @Repository, @Controller
}
// 3. 条件化配置
@Configuration
public class DatabaseConfig {
@Bean
@ConditionalOnProperty(name = "database.type", havingValue = "mysql")
public DataSource mysqlDataSource() {
return new MysqlDataSource();
}
@Bean
@ConditionalOnProperty(name = "database.type", havingValue = "postgresql")
public DataSource postgresqlDataSource() {
return new PostgresqlDataSource();
}
}
2. 配置文件管理
application.properties
properties
# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 应用配置
app.name=MyApplication
app.version=1.0.0
app.email.enabled=true
app.email.host=smtp.gmail.com
application.yml (推荐)
yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
app:
name: MyApplication
version: 1.0.0
email:
enabled: true
host: smtp.gmail.com
使用配置属性
java
// 1. 单个属性注入
@Service
public class EmailService {
@Value("${app.email.host}")
private String emailHost;
@Value("${app.email.enabled:false}") // 默认值
private boolean emailEnabled;
public void sendEmail(String message) {
if (emailEnabled) {
System.out.println("通过 " + emailHost + " 发送邮件: " + message);
}
}
}
// 2. 配置类绑定
@ConfigurationProperties(prefix = "app")
@Component
public class AppProperties {
private String name;
private String version;
private Email email;
// getter和setter方法
public static class Email {
private boolean enabled;
private String host;
// getter和setter
}
}
// 使用配置类
@Service
public class ApplicationService {
@Autowired
private AppProperties appProperties;
public void printAppInfo() {
System.out.println("应用名称: " + appProperties.getName());
System.out.println("版本: " + appProperties.getVersion());
System.out.println("邮件启用: " + appProperties.getEmail().isEnabled());
}
}
✅ 第四部分:实战练习 - 简单的用户管理系统(90分钟)
1. 项目结构
bash
src/main/java/com/example/usermgmt/
├── Application.java # 应用入口
├── controller/
│ └── UserController.java # 控制器层
├── service/
│ ├── UserService.java # 业务逻辑层接口
│ └── UserServiceImpl.java # 业务逻辑实现
├── repository/
│ └── UserRepository.java # 数据访问层
├── model/
│ └── User.java # 用户实体
└── config/
└── AppConfig.java # 应用配置
2. 完整代码实现
用户实体
java
// User.java
public class User {
private Long id;
private String username;
private String email;
private int age;
// 构造函数
public User() {}
public User(String username, String email, int age) {
this.username = username;
this.email = email;
this.age = age;
}
// getter和setter方法
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "User{id=" + id + ", username='" + username +
"', email='" + email + "', age=" + age + "}";
}
}
数据访问层
java
// UserRepository.java
@Repository
public class UserRepository {
// 模拟数据库存储
private Map<Long, User> users = new ConcurrentHashMap<>();
private AtomicLong idGenerator = new AtomicLong(1);
public List<User> findAll() {
return new ArrayList<>(users.values());
}
public User findById(Long id) {
return users.get(id);
}
public User save(User user) {
if (user.getId() == null) {
user.setId(idGenerator.getAndIncrement());
}
users.put(user.getId(), user);
return user;
}
public void deleteById(Long id) {
users.remove(id);
}
public User findByUsername(String username) {
return users.values().stream()
.filter(user -> user.getUsername().equals(username))
.findFirst()
.orElse(null);
}
}
业务逻辑层
java
// UserService.java (接口)
public interface UserService {
List<User> getAllUsers();
User getUserById(Long id);
User createUser(User user);
User updateUser(Long id, User user);
void deleteUser(Long id);
User getUserByUsername(String username);
}
// UserServiceImpl.java (实现)
@Service
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
// 构造函数注入(推荐方式)
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public List<User> getAllUsers() {
List<User> users = userRepository.findAll();
System.out.println("获取所有用户,总数: " + users.size());
return users;
}
@Override
public User getUserById(Long id) {
User user = userRepository.findById(id);
if (user == null) {
throw new RuntimeException("用户不存在: " + id);
}
return user;
}
@Override
public User createUser(User user) {
// 业务验证
if (user.getUsername() == null || user.getUsername().trim().isEmpty()) {
throw new RuntimeException("用户名不能为空");
}
// 检查用户名是否已存在
if (userRepository.findByUsername(user.getUsername()) != null) {
throw new RuntimeException("用户名已存在: " + user.getUsername());
}
User savedUser = userRepository.save(user);
System.out.println("创建用户成功: " + savedUser);
return savedUser;
}
@Override
public User updateUser(Long id, User user) {
User existingUser = getUserById(id);
existingUser.setUsername(user.getUsername());
existingUser.setEmail(user.getEmail());
existingUser.setAge(user.getAge());
User updatedUser = userRepository.save(existingUser);
System.out.println("更新用户成功: " + updatedUser);
return updatedUser;
}
@Override
public void deleteUser(Long id) {
User user = getUserById(id);
userRepository.deleteById(id);
System.out.println("删除用户成功: " + user);
}
@Override
public User getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
}
控制器层
java
// UserController.java
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
// 构造函数注入
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.updateUser(id, user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
@GetMapping("/search")
public User getUserByUsername(@RequestParam String username) {
return userService.getUserByUsername(username);
}
}
应用入口
java
// Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
// 可选:添加一些初始数据
@Bean
public CommandLineRunner initData(UserService userService) {
return args -> {
userService.createUser(new User("张三", "zhangsan@example.com", 25));
userService.createUser(new User("李四", "lisi@example.com", 30));
userService.createUser(new User("王五", "wangwu@example.com", 28));
System.out.println("初始化数据完成!");
};
}
}
✅ 第五部分:测试和验证(30分钟)
1. 创建测试类
java
// UserServiceTest.java
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testCreateUser() {
User user = new User("测试用户", "test@example.com", 22);
User savedUser = userService.createUser(user);
assertNotNull(savedUser.getId());
assertEquals("测试用户", savedUser.getUsername());
assertEquals("test@example.com", savedUser.getEmail());
assertEquals(22, savedUser.getAge());
}
@Test
public void testGetAllUsers() {
List<User> users = userService.getAllUsers();
assertTrue(users.size() >= 3); // 至少有初始化的3个用户
}
@Test
public void testUpdateUser() {
// 先创建用户
User user = new User("原始用户", "original@example.com", 20);
User savedUser = userService.createUser(user);
// 更新用户
User updateData = new User("更新用户", "updated@example.com", 25);
User updatedUser = userService.updateUser(savedUser.getId(), updateData);
assertEquals("更新用户", updatedUser.getUsername());
assertEquals("updated@example.com", updatedUser.getEmail());
assertEquals(25, updatedUser.getAge());
}
}
2. 使用Postman或curl测试API
bash
# 1. 获取所有用户
curl -X GET http://localhost:8080/api/users
# 2. 创建新用户
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"username":"新用户","email":"newuser@example.com","age":26}'
# 3. 获取特定用户
curl -X GET http://localhost:8080/api/users/1
# 4. 更新用户
curl -X PUT http://localhost:8080/api/users/1 \
-H "Content-Type: application/json" \
-d '{"username":"更新的用户","email":"updated@example.com","age":27}'
# 5. 删除用户
curl -X DELETE http://localhost:8080/api/users/1
# 6. 按用户名搜索
curl -X GET "http://localhost:8080/api/users/search?username=张三"
📝 今日学习总结
✅ 学习成果检查清单
- 理解Spring框架的核心概念(IoC、DI)
- 掌握三种依赖注入方式
- 了解Bean的生命周期和作用域
- 熟悉基于注解的配置方式
- 能够使用配置文件管理应用属性
- 完成用户管理系统实战项目
- 编写单元测试验证功能
🎯 重点掌握概念
- IoC容器:Spring管理所有Bean的生命周期
- 依赖注入:通过构造函数、setter或字段注入依赖
- 注解驱动:使用@Service、@Repository、@Controller等注解
- 配置外部化:使用application.yml管理配置
- 分层架构:Controller → Service → Repository的清晰分层
🚀 明天预告
第9天学习内容:Spring Boot Web开发
- RESTful API设计原则
- Spring MVC架构详解
- 请求映射和参数绑定
- 响应处理和异常处理
- 数据校验和转换