引言
Spring框架是Java企业级开发中最流行、最强大的框架之一。自2003年首次发布以来,Spring已经发展成为一个庞大的生态系统,涵盖了从依赖注入到微服务架构的各个方面。本文将从基础概念开始,逐步深入到高级特性和实战技巧,帮助你系统地掌握Spring框架。
第一部分:Spring基础概念
1.1 Spring框架概述
Spring是一个开源的Java开发框架,其核心设计目标是简化企业级应用的开发。Spring的主要特性包括:
- 控制反转(IoC):将对象的创建和管理交给Spring容器
- 依赖注入(DI):自动将依赖关系注入到对象中
- 面向切面编程(AOP):实现横切关注点的分离
- 声明式事务管理:简化事务处理
- 集成支持:与各种持久化技术、Web框架等无缝集成
1.2 Spring核心模块
Spring框架由多个模块组成,每个模块都有特定的功能:
// Spring核心模块示例
// 1. Spring Core - 提供IoC容器和DI支持
// 2. Spring Context - 提供应用上下文
// 3. Spring AOP - 面向切面编程
// 4. Spring JDBC - 简化JDBC操作
// 5. Spring ORM - 集成ORM框架
// 6. Spring Web - Web应用支持
// 7. Spring MVC - Web MVC框架
1.3 Spring Boot简介
Spring Boot是Spring框架的扩展,旨在简化Spring应用的初始搭建和开发过程:
// Spring Boot应用示例
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
第二部分:依赖注入与IoC容器
2.1 IoC容器基础
Spring IoC容器负责管理应用中的对象(称为Bean)及其生命周期。
2.1.1 Bean定义方式
XML配置方式:
<!-- beans.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="userRepository"/>
</bean>
<!-- Setter注入 -->
<bean id="userRepository" class="com.example.repository.UserRepository">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 工厂方法创建Bean -->
<bean id="connectionFactory" class="com.example.ConnectionFactory"
factory-method="getInstance"/>
</beans>
注解方式:
// 使用@Component注解
@Component
public class UserService {
private final UserRepository userRepository;
// 构造器注入(推荐)
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 方法注入
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
// 使用@Service、@Repository、@Controller等特定注解
@Service
public class UserServiceImpl implements UserService {
// ...
}
@Repository
public class UserRepositoryImpl implements UserRepository {
// ...
}
Java配置方式:
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService(userRepository());
}
@Bean
public UserRepository userRepository() {
return new UserRepositoryImpl();
}
// 条件化Bean创建
@Bean
@ConditionalOnMissingBean
public DataSource dataSource() {
return new HikariDataSource();
}
}
2.2 依赖注入的三种方式
2.2.1 构造器注入(推荐)
@Service
public class OrderService {
private final PaymentService paymentService;
private final NotificationService notificationService;
// 构造器注入 - 依赖不可变,且明确依赖关系
@Autowired
public OrderService(PaymentService paymentService,
NotificationService notificationService) {
this.paymentService = paymentService;
this.notificationService = notificationService;
}
public void processOrder(Order order) {
paymentService.processPayment(order);
notificationService.sendOrderConfirmation(order);
}
}
2.2.2 Setter注入
@Service
public class OrderService {
private PaymentService paymentService;
private NotificationService notificationService;
// Setter注入 - 适合可选依赖
@Autowired
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
@Autowired
public void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}
}
2.2.3 字段注入(不推荐)
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
@Autowired
private NotificationService notificationService;
// 字段注入的问题:
// 1. 难以测试(需要反射或Spring容器)
// 2. 依赖关系不明确
// 3. 可能导致循环依赖
}
2.3 Bean的作用域
Spring支持多种Bean作用域:
@Component
@Scope("singleton") // 单例(默认)
public class SingletonBean {
// 整个Spring容器中只有一个实例
}
@Component
@Scope("prototype") // 原型
public class PrototypeBean {
// 每次请求都会创建新实例
}
@Component
@Scope("request") // 请求作用域(Web环境)
public class RequestScopedBean {
// 每个HTTP请求一个实例
}
@Component
@Scope("session") // 会话作用域(Web环境)
public class SessionScopedBean {
// 每个HTTP会话一个实例
}
@Component
@Scope("application") // 应用作用域(Web环境)
public class ApplicationScopedBean {
// 整个Web应用一个实例
}
2.4 Bean生命周期管理
@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
// 构造器
public LifecycleBean() {
System.out.println("1. 构造器调用");
}
// @PostConstruct注解
@PostConstruct
public void postConstruct() {
System.out.println("2. @PostConstruct调用");
}
// InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("3. afterPropertiesSet调用");
}
// 自定义初始化方法
@Bean(initMethod = "customInit")
public void customInit() {
System.out.println("4. 自定义初始化方法");
}
// @PreDestroy注解
@PreDestroy
public void preDestroy() {
System.out.println("5. @PreDestroy调用");
}
// DisposableBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("6. destroy调用");
}
// 自定义销毁方法
@Bean(destroyMethod = "customDestroy")
public void customDestroy() {
System.out.println("7. 自定义销毁方法");
}
}
第三部分:Spring AOP(面向切面编程)
3.1 AOP核心概念
- 切面(Aspect):横切关注点的模块化
- 连接点(Join Point):程序执行过程中的某个点
- 通知(Advice):在连接点执行的具体操作
- 切入点(Pointcut):匹配连接点的表达式
- 目标对象(Target):被代理的对象
3.2 AOP实现方式
3.2.1 基于注解的AOP
// 1. 定义切面
@Aspect
@Component
public class LoggingAspect {
// 切入点表达式:匹配所有Service层的方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
// 前置通知
@Before("serviceMethods()")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行方法: " + methodName + " 前");
}
// 后置通知
@After("serviceMethods()")
public void logAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行方法: " + methodName + " 后");
}
// 返回通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("方法: " + methodName + " 返回: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("方法: " + methodName + " 抛出异常: " + ex.getMessage());
}
// 环绕通知
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
System.out.println("方法: " + methodName + " 开始执行");
try {
Object result = joinPoint.proceed(); // 执行目标方法
System.out.println("方法: " + methodName + " 执行成功");
return result;
} catch (Exception e) {
System.out.println("方法: " + methodName + " 执行失败: " + e.getMessage());
throw e;
}
}
}
3.2.2 基于XML的AOP配置
<!-- aop-config.xml -->
<aop:config>
<!-- 定义切面 -->
<aop:aspect ref="loggingAspect">
<!-- 定义切入点 -->
<aop:pointcut id="serviceMethods"
expression="execution(* com.example.service.*.*(..))"/>
<!-- 前置通知 -->
<aop:before pointcut-ref="serviceMethods"
method="logBefore"/>
<!-- 后置通知 -->
<aop:after pointcut-ref="serviceMethods"
method="logAfter"/>
</aop:aspect>
</aop:config>
<bean id="loggingAspect" class="com.example.aspect.LoggingAspect"/>
3.3 AOP实战:事务管理
// 使用Spring的声明式事务管理
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private PaymentService paymentService;
// @Transactional注解配置事务
@Transactional(
propagation = Propagation.REQUIRED, // 事务传播行为
isolation = Isolation.READ_COMMITTED, // 隔离级别
timeout = 30, // 超时时间
rollbackFor = {Exception.class}, // 回滚异常
noRollbackFor = {NullPointerException.class} // 不回滚异常
)
public void processOrder(Order order) {
// 1. 保存订单
orderRepository.save(order);
// 2. 处理支付
paymentService.processPayment(order);
// 3. 发送通知
sendNotification(order);
}
// 事务传播行为示例
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void processPaymentInNewTransaction(Order order) {
// 这个方法会在新的事务中执行
paymentService.processPayment(order);
}
// 只读事务
@Transactional(readOnly = true)
public List<Order> findOrdersByUser(Long userId) {
return orderRepository.findByUserId(userId);
}
}
第四部分:Spring MVC
4.1 Spring MVC架构
Spring MVC遵循经典的MVC模式:
- Model:数据模型
- View:视图(JSP、Thymeleaf等)
- Controller:控制器
4.2 创建Controller
// 1. 基础Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// GET请求 - 获取用户列表
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.findAll();
return ResponseEntity.ok(users);
}
// GET请求 - 获取单个用户
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.findById(id);
return ResponseEntity.ok(user);
}
// POST请求 - 创建用户
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
// PUT请求 - 更新用户
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@RequestBody User user) {
user.setId(id);
User updatedUser = userService.update(user);
return ResponseEntity.ok(updatedUser);
}
// DELETE请求 - 删除用户
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
}
4.3 请求参数处理
@RestController
@RequestMapping("/api/orders")
public class OrderController {
// 路径参数
@GetMapping("/{id}")
public Order getOrderById(@PathVariable Long id) {
return orderService.findById(id);
}
// 查询参数
@GetMapping("/search")
public List<Order> searchOrders(@RequestParam String status,
@RequestParam(defaultValue = "10") int limit) {
return orderService.findByStatus(status, limit);
}
// 请求体参数
@PostMapping
public Order createOrder(@RequestBody Order order) {
return orderService.create(order);
}
// 表单参数
@PostMapping("/form")
public Order createOrderFromForm(@RequestParam String customerName,
@RequestParam String productCode) {
Order order = new Order();
order.setCustomerName(customerName);
order.setProductCode(productCode);
return orderService.create(order);
}
// 复杂对象参数
@PostMapping("/complex")
public Order createComplexOrder(@RequestBody OrderRequest request) {
// OrderRequest包含多个字段和嵌套对象
return orderService.create(request.toOrder());
}
// 文件上传
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("文件不能为空");
}
try {
// 处理文件
String fileName = file.getOriginalFilename();
// 保存文件逻辑...
return ResponseEntity.ok("文件上传成功: " + fileName);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("文件上传失败: " + e.getMessage());
}
}
}
4.4 数据验证
// 1. 定义验证注解
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EmailValidator.class)
public @interface ValidEmail {
String message() default "无效的邮箱格式";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 2. 实现验证器
public class EmailValidator implements ConstraintValidator<ValidEmail, String> {
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
if (email == null) return true;
return email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
}
// 3. 在实体类中使用
public class User {
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度必须在3-20之间")
private String username;
@ValidEmail
private String email;
@Min(value = 18, message = "年龄必须大于等于18岁")
@Max(value = 100, message = "年龄不能超过100岁")
private Integer age;
// getters and setters
}
// 4. 在Controller中使用
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// 收集所有错误信息
List<String> errors = bindingResult.getAllErrors()
.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(null);
}
User savedUser = userService.save(user);
return ResponseEntity.ok(savedUser);
}
}
第五部分:Spring Data JPA
5.1 JPA基础
// 1. 实体类定义
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false, length = 50)
private String username;
@Column(name = "email", unique = true)
private String email;
@Column(name = "age")
private Integer age;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Order> orders = new ArrayList<>();
// 构造函数、getter、setter
}
// 2. Repository接口
public interface UserRepository extends JpaRepository<User, Long> {
// 自定义查询方法
User findByUsername(String username);
List<User> findByAgeGreaterThan(Integer age);
// 使用JPQL查询
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
// 原生SQL查询
@Query(value = "SELECT * FROM users WHERE age > :age", nativeQuery = true)
List<User> findUsersByAgeGreaterThan(@Param("age") Integer age);
// 分页查询
Page<User> findByAgeGreaterThan(Integer age, Pageable pageable);
// 排序查询
List<User> findByAgeGreaterThan(Integer age, Sort sort);
// 自定义更新操作
@Modifying
@Query("UPDATE User u SET u.age = :age WHERE u.id = :id")
int updateAge(@Param("id") Long id, @Param("age") Integer age);
// 自定义删除操作
@Modifying
@Query("DELETE FROM User u WHERE u.age < :minAge")
int deleteUsersByAgeLessThan(@Param("minAge") Integer minAge);
}
5.2 事务管理
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private OrderRepository orderRepository;
// 事务传播行为示例
@Transactional(propagation = Propagation.REQUIRED)
public User createUserWithOrders(User user, List<Order> orders) {
// 保存用户
user = userRepository.save(user);
// 设置订单关联
orders.forEach(order -> order.setUser(user));
// 保存订单
orderRepository.saveAll(orders);
return user;
}
// 事务回滚示例
@Transactional(rollbackFor = Exception.class)
public void processUserWithRollback(User user) {
userRepository.save(user);
// 模拟异常
if (user.getAge() < 18) {
throw new RuntimeException("年龄不能小于18岁");
}
// 这行代码不会执行,因为上面抛出了异常
System.out.println("用户处理完成");
}
// 只读事务
@Transactional(readOnly = true)
public List<User> findAllUsers() {
return userRepository.findAll();
}
}
第六部分:Spring Security
6.1 基础配置
// 1. 安全配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // 禁用CSRF(对于REST API)
.authorizeHttpRequests(authz -> authz
// 允许匿名访问的端点
.requestMatchers("/api/public/**").permitAll()
// 需要认证的端点
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
// 其他所有请求都需要认证
.anyRequest().authenticated()
)
// 表单登录配置
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll()
)
// HTTP Basic认证
.httpBasic(basic -> basic
.realmName("MyApp")
)
// 登出配置
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
);
return http.build();
}
// 密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 用户详情服务
@Bean
public UserDetailsService userDetailsService() {
// 基于内存的用户存储
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("password"))
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin123"))
.roles("ADMIN", "USER")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
6.2 基于数据库的认证
// 1. 实体类
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String email;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
// getters and setters
}
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String name; // ROLE_USER, ROLE_ADMIN
@ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<>();
// getters and setters
}
// 2. Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
// 3. 自定义UserDetailsService
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + username));
return org.springframework.security.core.userdetails.User
.withUsername(user.getUsername())
.password(user.getPassword())
.authorities(user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList()))
.build();
}
}
// 4. 更新安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private CustomUserDetailsService userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll()
)
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
);
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
第七部分:Spring Boot实战
7.1 Spring Boot项目结构
my-spring-boot-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── myapp/
│ │ │ ├── Application.java # 主启动类
│ │ │ ├── config/ # 配置类
│ │ │ ├── controller/ # 控制器
│ │ │ ├── service/ # 服务层
│ │ │ ├── repository/ # 数据访问层
│ │ │ ├── entity/ # 实体类
│ │ │ ├── dto/ # 数据传输对象
│ │ │ └── exception/ # 异常处理
│ │ └── resources/
│ │ ├── application.yml # 主配置文件
│ │ ├── application-dev.yml # 开发环境配置
│ │ ├── application-prod.yml # 生产环境配置
│ │ └── static/ # 静态资源
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── myapp/
│ └── test/ # 测试类
└── pom.xml # Maven配置
7.2 配置管理
# application.yml
server:
port: 8080
servlet:
context-path: /api
spring:
# 数据源配置
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
connection-timeout: 30000
# JPA配置
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect
# 邮件配置
mail:
host: smtp.gmail.com
port: 587
username: your-email@gmail.com
password: your-password
properties:
mail:
smtp:
auth: true
starttls:
enable: true
# 缓存配置
cache:
type: redis
redis:
time-to-live: 3600000
# 消息队列配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
# 自定义配置
app:
name: My Spring Boot Application
version: 1.0.0
features:
email-notifications: true
sms-notifications: false
admin-emails:
- admin1@example.com
- admin2@example.com
7.3 配置类示例
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private String version;
private Features features;
private List<String> adminEmails = new ArrayList<>();
// Getters and Setters
public static class Features {
private boolean emailNotifications;
private boolean smsNotifications;
// Getters and Setters
}
@Bean
public EmailService emailService() {
return new EmailService(features.emailNotifications);
}
}
7.4 Spring Boot Starter
// 1. 创建自定义Starter
// pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
// 2. 配置类
@Configuration
@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class CustomDataSourceAutoConfiguration {
@Bean
@ConfigurationProperties(prefix = "custom.datasource")
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}
// 3. 配置属性类
@ConfigurationProperties(prefix = "custom.datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
private String driverClassName;
// Getters and Setters
}
第八部分:Spring高级特性
8.1 事件驱动编程
// 1. 自定义事件
public class UserRegisteredEvent extends ApplicationEvent {
private User user;
public UserRegisteredEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
// 2. 事件发布者
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void registerUser(User user) {
// 保存用户
userRepository.save(user);
// 发布事件
eventPublisher.publishEvent(new UserRegisteredEvent(this, user));
}
}
// 3. 事件监听器
@Component
public class UserEventListener {
@EventListener
public void handleUserRegistered(UserRegisteredEvent event) {
User user = event.getUser();
System.out.println("用户注册事件处理: " + user.getUsername());
// 发送欢迎邮件
emailService.sendWelcomeEmail(user.getEmail());
// 记录日志
logService.logUserRegistration(user.getId());
}
@EventListener
@Async // 异步处理
public void handleUserRegisteredAsync(UserRegisteredEvent event) {
// 异步处理,不阻塞主线程
System.out.println("异步处理用户注册事件");
}
}
8.2 异步处理
// 1. 启用异步支持
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
// 2. 异步方法
@Service
public class EmailService {
@Async
public CompletableFuture<String> sendEmail(String to, String subject, String content) {
try {
// 模拟发送邮件
Thread.sleep(2000);
System.out.println("发送邮件到: " + to);
return CompletableFuture.completedFuture("邮件发送成功");
} catch (InterruptedException e) {
return CompletableFuture.failedFuture(e);
}
}
@Async
public void sendBulkEmails(List<String> recipients) {
recipients.forEach(recipient -> {
sendEmail(recipient, "通知", "您的订单已处理");
});
}
}
// 3. 异步调用
@Service
public class OrderService {
@Autowired
private EmailService emailService;
public void processOrder(Order order) {
// 同步处理订单
orderRepository.save(order);
// 异步发送邮件
CompletableFuture<String> emailFuture = emailService.sendEmail(
order.getCustomerEmail(),
"订单确认",
"您的订单已确认"
);
// 可以继续其他操作,不等待邮件发送完成
System.out.println("订单处理完成,邮件发送中...");
// 如果需要等待结果
emailFuture.thenAccept(result -> {
System.out.println("邮件发送结果: " + result);
});
}
}
8.3 缓存管理
// 1. 启用缓存
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
// 使用Redis作为缓存
RedisCacheManager redisCacheManager = RedisCacheManager.builder(
RedisConnectionFactory.create())
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))
.disableCachingNullValues())
.build();
return redisCacheManager;
}
}
// 2. 使用缓存注解
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 缓存查询结果
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
System.out.println("从数据库查询用户: " + id);
return userRepository.findById(id).orElse(null);
}
// 更新缓存
@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
System.out.println("更新用户: " + user.getId());
return userRepository.save(user);
}
// 删除缓存
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
System.out.println("删除用户: " + id);
userRepository.deleteById(id);
}
// 条件缓存
@Cacheable(value = "users", key = "#id", unless = "#result == null")
public User getUserByIdConditional(Long id) {
return userRepository.findById(id).orElse(null);
}
}
第九部分:Spring测试
9.1 单元测试
// 1. 使用JUnit 5和Mockito
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private EmailService emailService;
@InjectMocks
private UserService userService;
@Test
void shouldCreateUser() {
// 准备测试数据
User user = new User();
user.setUsername("testuser");
user.setEmail("test@example.com");
// 模拟行为
when(userRepository.save(any(User.class))).thenReturn(user);
doNothing().when(emailService).sendWelcomeEmail(anyString());
// 执行测试
User result = userService.createUser(user);
// 验证结果
assertNotNull(result);
assertEquals("testuser", result.getUsername());
// 验证方法调用
verify(userRepository, times(1)).save(user);
verify(emailService, times(1)).sendWelcomeEmail("test@example.com");
}
@Test
void shouldThrowExceptionWhenUserExists() {
// 准备测试数据
User user = new User();
user.setUsername("existinguser");
// 模拟行为
when(userRepository.findByUsername("existinguser"))
.thenReturn(Optional.of(user));
// 执行测试并验证异常
assertThrows(UserAlreadyExistsException.class, () -> {
userService.createUser(user);
});
}
}
9.2 集成测试
// 1. Spring Boot集成测试
@SpringBootTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Transactional // 测试完成后回滚
class UserServiceIntegrationTest {
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
@Test
void shouldCreateUserAndSaveToDatabase() {
// 准备测试数据
User user = new User();
user.setUsername("integrationtest");
user.setEmail("integration@test.com");
// 执行测试
User savedUser = userService.createUser(user);
// 验证结果
assertNotNull(savedUser.getId());
// 验证数据库
User foundUser = userRepository.findById(savedUser.getId()).orElse(null);
assertNotNull(foundUser);
assertEquals("integrationtest", foundUser.getUsername());
}
}
// 2. Web层集成测试
@WebMvcTest(UserController.class)
class UserControllerWebTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void shouldGetUserById() throws Exception {
// 准备测试数据
User user = new User();
user.setId(1L);
user.setUsername("testuser");
// 模拟行为
when(userService.getUserById(1L)).thenReturn(user);
// 执行测试
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(1))
.andExpect(jsonPath("$.username").value("testuser"));
}
}
第十部分:Spring Cloud微服务
10.1 Spring Cloud基础
// 1. 服务注册与发现(Eureka)
// 服务提供者
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
// application.yml
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
// 2. 服务消费者
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@GetMapping("/orders/{id}")
public Order getOrderWithUser(@PathVariable Long id) {
// 通过服务名调用,而不是直接调用IP
User user = restTemplate.getForObject(
"http://user-service/api/users/{userId}",
User.class,
order.getUserId()
);
Order order = orderService.getOrder(id);
order.setUser(user);
return order;
}
}
10.2 API网关(Spring Cloud Gateway)
// 1. 网关配置
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.uri("lb://user-service"))
.route("order-service", r -> r
.path("/api/orders/**")
.uri("lb://order-service"))
.route("auth-service", r -> r
.path("/api/auth/**")
.uri("lb://auth-service"))
.build();
}
}
// 2. 自定义过滤器
@Component
public class LoggingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 请求前处理
System.out.println("请求路径: " + exchange.getRequest().getPath());
System.out.println("请求方法: " + exchange.getRequest().getMethod());
// 继续执行过滤器链
return chain.filter(exchange)
.doOnSuccess(v -> {
// 响应后处理
System.out.println("响应状态: " + exchange.getResponse().getStatusCode());
});
}
@Override
public int getOrder() {
return -1; // 优先级
}
}
10.3 配置中心(Spring Cloud Config)
// 1. 配置服务器
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
// application.yml
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/your-repo/config-repo
search-paths: config
username: your-username
password: your-password
default-label: main
// 2. 配置客户端
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
// bootstrap.yml
spring:
application:
name: user-service
cloud:
config:
uri: http://localhost:8888
profile: dev
label: main
第十一部分:性能优化与最佳实践
11.1 性能优化技巧
// 1. 数据库连接池优化
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public HikariDataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
// 优化配置
dataSource.setMaximumPoolSize(20); // 根据并发量调整
dataSource.setMinimumIdle(5);
dataSource.setConnectionTimeout(30000);
dataSource.setIdleTimeout(600000);
dataSource.setMaxLifetime(1800000);
dataSource.setLeakDetectionThreshold(60000);
return dataSource;
}
}
// 2. 查询优化
@Service
public class UserService {
// 避免N+1查询问题
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders WHERE u.id = :id")
User getUserWithOrders(@Param("id") Long id);
// 使用分页查询
public Page<User> findUsersByAge(Integer age, int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("username"));
return userRepository.findByAgeGreaterThan(age, pageable);
}
// 批量操作
@Transactional
public void batchUpdateUsers(List<User> users) {
users.forEach(user -> {
userRepository.save(user);
});
}
}
// 3. 缓存优化
@Service
public class ProductService {
@Cacheable(value = "products", key = "#id",
unless = "#result == null",
sync = true) // 防止缓存击穿
public Product getProductById(Long id) {
return productRepository.findById(id).orElse(null);
}
@Cacheable(value = "products", key = "'category:' + #category")
public List<Product> getProductsByCategory(String category) {
return productRepository.findByCategory(category);
}
}
11.2 最佳实践
// 1. 分层架构
// Controller层 - 只负责请求处理和响应
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
User user = userService.getUserById(id);
return ResponseEntity.ok(UserDTO.from(user));
}
}
// Service层 - 业务逻辑
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private EmailService emailService;
public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
}
public User createUser(User user) {
// 业务验证
if (userRepository.existsByUsername(user.getUsername())) {
throw new UserAlreadyExistsException(user.getUsername());
}
// 保存用户
User savedUser = userRepository.save(user);
// 发送通知
emailService.sendWelcomeEmail(savedUser.getEmail());
return savedUser;
}
}
// Repository层 - 数据访问
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
boolean existsByUsername(String username);
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email);
}
// DTO层 - 数据传输对象
public class UserDTO {
private Long id;
private String username;
private String email;
private Integer age;
// 构造函数、getter、setter
public static UserDTO from(User user) {
UserDTO dto = new UserDTO();
dto.setId(user.getId());
dto.setUsername(user.getUsername());
dto.setEmail(user.getEmail());
dto.setAge(user.getAge());
return dto;
}
}
// 2. 异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleUserNotFound(UserNotFoundException ex) {
return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
}
@ExceptionHandler(UserAlreadyExistsException.class)
@ResponseStatus(HttpStatus.CONFLICT)
public ErrorResponse handleUserAlreadyExists(UserAlreadyExistsException ex) {
return new ErrorResponse("USER_ALREADY_EXISTS", ex.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult().getAllErrors()
.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
return new ErrorResponse("VALIDATION_ERROR", String.join(", ", errors));
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleGenericException(Exception ex) {
return new ErrorResponse("INTERNAL_ERROR", "系统内部错误");
}
}
// 3. 配置管理
@Configuration
public class AppConfig {
@Value("${app.feature.enabled:false}")
private boolean featureEnabled;
@Bean
@ConditionalOnProperty(name = "app.feature.enabled", havingValue = "true")
public FeatureService featureService() {
return new FeatureService();
}
@Bean
@ConditionalOnMissingBean(FeatureService.class)
public FeatureService defaultFeatureService() {
return new DefaultFeatureService();
}
}
第十二部分:Spring学习路线图
12.1 初级阶段(1-2个月)
- Java基础:掌握Java核心语法、集合框架、多线程
- Spring Core:深入理解IoC、DI、Bean生命周期
- Spring MVC:掌握Web开发基础
- Spring Data JPA:学习数据库操作
- Spring Boot:快速搭建项目
12.2 中级阶段(3-4个月)
- Spring AOP:掌握面向切面编程
- Spring Security:学习安全认证与授权
- Spring事务管理:理解事务传播行为
- Spring测试:单元测试与集成测试
- 性能优化:数据库优化、缓存策略
12.3 高级阶段(5-6个月)
- Spring Cloud:微服务架构
- Spring Boot高级特性:自定义Starter、自动配置
- 设计模式:在Spring中应用设计模式
- 架构设计:DDD、Clean Architecture
- 监控与运维:Actuator、Micrometer
12.4 专家阶段(持续学习)
- 源码阅读:深入Spring源码
- 框架扩展:自定义Spring组件
- 性能调优:JVM调优、GC优化
- 云原生:Kubernetes、Docker集成
- 领域专家:特定行业解决方案
结语
Spring框架是一个庞大而强大的生态系统,掌握它需要时间和实践。本文从基础概念到高级特性,系统地介绍了Spring的核心知识点。学习Spring的关键在于:
- 理论与实践结合:每个概念都要通过代码实践来理解
- 循序渐进:不要急于求成,打好基础再进阶
- 阅读源码:理解Spring的内部机制
- 参与社区:关注Spring官方文档和社区动态
- 持续学习:技术不断更新,保持学习热情
记住,最好的学习方式是动手实践。建议从一个简单的项目开始,逐步添加复杂功能,最终构建一个完整的应用。祝你在Spring的学习之旅中取得成功!
