引言:为什么选择Spring框架?
Spring框架是Java企业级应用开发的事实标准,它解决了企业级开发中的诸多难题。Spring的核心理念是”控制反转”(IoC)和”面向切面编程”(AOP),通过这两项核心技术,Spring极大地简化了Java开发,提高了代码的可测试性、可维护性和灵活性。
在企业级应用中,我们经常面临以下挑战:
- 对象之间复杂的依赖关系管理
- 事务管理的复杂性
- 代码重复(如日志、安全等横切关注点)
- 与各种第三方技术的集成
Spring框架通过其模块化的设计和丰富的生态系统,为这些挑战提供了优雅的解决方案。无论你是刚入门的Java开发者,还是有经验的工程师,掌握Spring都将为你的职业生涯带来巨大价值。
第一部分:Spring基础核心概念
1.1 控制反转(IoC)与依赖注入(DI)
控制反转(Inversion of Control, IoC)是Spring框架最核心的概念之一。传统的编程方式中,程序主动创建和管理对象之间的依赖关系;而IoC则是将对象的创建和管理权交给了容器,程序只需要声明需要什么,容器就会提供什么。
依赖注入(Dependency Injection, DI)是IoC的具体实现方式。Spring通过以下三种方式实现依赖注入:
- 构造器注入:通过构造函数传递依赖
- Setter方法注入:通过setter方法设置依赖
- 字段注入:直接在字段上使用注解
让我们通过一个实际例子来理解这些概念:
// 传统方式:程序主动创建依赖
public class UserService {
private UserRepository userRepository = new UserRepository();
public void register(String username) {
// 注册逻辑
userRepository.save(username);
}
}
// Spring方式:依赖注入
public class UserService {
private final UserRepository userRepository;
// 构造器注入
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void register(String username) {
userRepository.save(username);
}
}
在Spring中,我们通常使用注解来标记组件和依赖:
@Component
public class UserRepository {
public void save(String username) {
System.out.println("保存用户: " + username);
}
}
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void register(String username) {
userRepository.save(username);
}
}
1.2 Spring Bean的生命周期
理解Bean的生命周期对于掌握Spring至关重要。Spring Bean从创建到销毁经历以下阶段:
- 实例化:通过构造函数创建Bean实例
- 属性填充:设置Bean的属性值
- 初始化前:调用BeanPostProcessor的postProcessBeforeInitialization方法
- 初始化:调用InitializingBean的afterPropertiesSet方法或自定义init方法
- 初始化后:调用BeanPostProcessor的postProcessAfterInitialization方法
- 使用:Bean已就绪,可以被应用程序使用
- 销毁:调用DisposableBean的destroy方法或自定义destroy方法
我们可以通过实现特定的接口或使用注解来参与到Bean的生命周期中:
@Component
public class MyBean implements InitializingBean, DisposableBean {
public MyBean() {
System.out.println("1. 构造函数调用");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("3. 初始化方法调用");
}
@PreDestroy
public void customDestroy() {
System.out.println("7. 自定义销毁方法调用");
}
@Override
public void destroy() throws Exception {
System.out.println("7. DisposableBean.destroy()调用");
}
@PostConstruct
public void customInit() {
System.out.println("4. @PostConstruct方法调用");
}
}
1.3 Spring配置方式
Spring支持多种配置方式,包括XML配置、注解配置和Java配置。现代Spring开发主要使用注解和Java配置。
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="userRepository" class="com.example.UserRepository"/>
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userRepository"/>
</bean>
</beans>
注解配置示例:
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// 配置Bean
}
Java配置示例:
@Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new UserRepository();
}
@Bean
public UserService userService() {
return new UserService(userRepository());
}
}
第二部分:Spring核心原理深入解析
2.1 Spring AOP原理与应用
面向切面编程(Aspect-Oriented Programming, AOP)是Spring的另一大核心特性。AOP允许我们分离横切关注点(如日志、安全、事务等),使业务逻辑更加纯粹。
Spring AOP基于代理模式实现,主要支持以下类型的增强:
- 前置通知(Before Advice):在目标方法执行前执行
- 后置通知(After Returning Advice):在目标方法成功执行后执行
- 异常通知(After Throwing Advice):在目标方法抛出异常后执行
- 最终通知(After Finally Advice):无论目标方法是否成功都会执行
- 环绕通知(Around Advice):最强大的通知类型,可以控制目标方法的执行
让我们通过一个完整的日志切面示例来理解AOP:
// 定义切面
@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();
Object[] args = joinPoint.getArgs();
System.out.println("[LOG] 执行方法: " + methodName +
", 参数: " + Arrays.toString(args));
}
// 后置通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[LOG] 方法 " + methodName + " 执行成功, 返回: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[ERROR] 方法 " + methodName + " 执行异常: " + ex.getMessage());
}
// 环绕通知
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
System.out.println("[PERF] 方法执行耗时: " + duration + "ms");
return result;
} catch (Exception e) {
long duration = System.currentTimeMillis() - start;
System.out.println("[ERROR] 方法执行失败,耗时: " + duration + "ms");
throw e;
}
}
}
2.2 Spring事务管理
Spring提供了强大的事务管理抽象,支持声明式事务和编程式事务。声明式事务通过AOP实现,是最常用的方式。
声明式事务示例:
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final InventoryRepository inventoryRepository;
@Autowired
public OrderService(OrderRepository orderRepository,
InventoryRepository inventoryRepository) {
this.orderRepository = orderRepository;
this.inventoryRepository = inventoryRepository;
}
@Transactional
public void createOrder(Order order) {
// 1. 保存订单
orderRepository.save(order);
// 2. 扣减库存
inventoryRepository.decreaseStock(order.getProductId(), order.getQuantity());
// 如果这里抛出异常,整个事务会回滚
if (order.getQuantity() <= 0) {
throw new IllegalArgumentException("订单数量必须大于0");
}
}
}
事务传播行为:
Spring定义了7种事务传播行为,通过@Transactional(propagation = Propagation.XXX)设置:
- REQUIRED(默认):如果当前存在事务,则加入;否则创建新事务
- REQUIRES_NEW:总是创建新事务,如果当前存在事务,则挂起当前事务
- NESTED:如果当前存在事务,则在嵌套事务中执行;否则创建新事务
- SUPPORTS:如果当前存在事务,则加入;否则以非事务方式执行
- NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则挂起
- MANDATORY:如果当前存在事务,则加入;否则抛出异常
- NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
事务隔离级别:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateProduct(Product product) {
// 业务逻辑
}
2.3 Spring事件驱动模型
Spring提供了强大的事件驱动模型,允许组件之间进行松耦合的通信。
自定义事件:
public class OrderCreatedEvent extends ApplicationEvent {
private final Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
public Order getOrder() {
return order;
}
}
事件发布者:
@Service
public class OrderService {
private final ApplicationEventPublisher eventPublisher;
@Autowired
public OrderService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Transactional
public void createOrder(Order order) {
// 保存订单
orderRepository.save(order);
// 发布事件
eventPublisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
事件监听器:
@Component
public class OrderEventListener {
// 异步处理
@Async
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
Order order = event.getOrder();
// 发送邮件通知
sendEmailNotification(order);
// 更新库存
updateInventory(order);
// 记录日志
logOrderCreation(order);
}
// 有序处理
@Order(1)
@EventListener
</function_calls>
</invoke>
<invoke name="generate_article">
<parameter name="title">Java开发框架Spring学习从入门到精通掌握核心原理与实战技巧解决企业级应用开发难题</parameter>
</invoke>
<parameter name="content">Spring框架是Java企业级应用开发的事实标准,它解决了企业级开发中的诸多难题。Spring的核心理念是"控制反转"(IoC)和"面向切面编程"(AOP),通过这两项核心技术,Spring极大地简化了Java开发,提高了代码的可测试性、可维护性和灵活性。
在企业级应用中,我们经常面临以下挑战:
- 对象之间复杂的依赖关系管理
- 事务管理的复杂性
- 代码重复(如日志、安全等横切关注点)
- 与各种第三方技术的集成
Spring框架通过其模块化的设计和丰富的生态系统,为这些挑战提供了优雅的解决方案。无论你是刚入门的Java开发者,还是有经验的工程师,掌握Spring都将为你的职业生涯带来巨大价值。
## 第一部分:Spring基础核心概念
### 1.1 控制反转(IoC)与依赖注入(DI)
控制反转(Inversion of Control, IoC)是Spring框架最核心的概念之一。传统的编程方式中,程序主动创建和管理对象之间的依赖关系;而IoC则是将对象的创建和管理权交给了容器,程序只需要声明需要什么,容器就会提供什么。
依赖注入(Dependency Injection, DI)是IoC的具体实现方式。Spring通过以下三种方式实现依赖注入:
1. **构造器注入**:通过构造函数传递依赖
2. **Setter方法注入**:通过setter方法设置依赖
3. **字段注入**:直接在字段上使用注解
让我们通过一个实际例子来理解这些概念:
```java
// 传统方式:程序主动创建依赖
public class UserService {
private UserRepository userRepository = new UserRepository();
public void register(String username) {
// 注册逻辑
userRepository.save(username);
}
}
// Spring方式:依赖注入
public class UserService {
private final UserRepository userRepository;
// 构造器注入
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void register(String username) {
userRepository.save(username);
}
}
在Spring中,我们通常使用注解来标记组件和依赖:
@Component
public class UserRepository {
public void save(String username) {
System.out.println("保存用户: " + username);
}
}
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void register(String username) {
userRepository.save(username);
}
}
1.2 Spring Bean的生命周期
理解Bean的生命周期对于掌握Spring至关重要。Spring Bean从创建到销毁经历以下阶段:
- 实例化:通过构造函数创建Bean实例
- 属性填充:设置Bean的属性值
- 初始化前:调用BeanPostProcessor的postProcessBeforeInitialization方法
- 初始化:调用InitializingBean的afterPropertiesSet方法或自定义init方法
- 初始化后:调用BeanPostProcessor的postProcessAfterInitialization方法
- 使用:Bean已就绪,可以被应用程序使用
- 销毁:调用DisposableBean的destroy方法或自定义destroy方法
我们可以通过实现特定的接口或使用注解来参与到Bean的生命周期中:
@Component
public class MyBean implements InitializingBean, DisposableBean {
public MyBean() {
System.out.println("1. 构造函数调用");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("3. 初始化方法调用");
}
@PreDestroy
public void customDestroy() {
System.out.println("7. 自定义销毁方法调用");
}
@Override
public void destroy() throws Exception {
System.out.println("7. DisposableBean.destroy()调用");
}
@PostConstruct
public void customInit() {
System.out.println("4. @PostConstruct方法调用");
}
}
1.3 Spring配置方式
Spring支持多种配置方式,包括XML配置、注解配置和Java配置。现代Spring开发主要使用注解和Java配置。
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="userRepository" class="com.example.UserRepository"/>
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userRepository"/>
</bean>
</beans>
注解配置示例:
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// 配置Bean
}
Java配置示例:
@Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new UserRepository();
}
@Bean
public UserService userService() {
return new UserService(userRepository());
}
}
第二部分:Spring核心原理深入解析
2.1 Spring AOP原理与应用
面向切面编程(Aspect-Oriented Programming, AOP)是Spring的另一大核心特性。AOP允许我们分离横切关注点(如日志、安全、事务等),使业务逻辑更加纯粹。
Spring AOP基于代理模式实现,主要支持以下类型的增强:
- 前置通知(Before Advice):在目标方法执行前执行
- 后置通知(After Returning Advice):在目标方法成功执行后执行
- 异常通知(After Throwing Advice):在目标方法抛出异常后执行
- 最终通知(After Finally Advice):无论目标方法是否成功都会执行
- 环绕通知(Around Advice):最强大的通知类型,可以控制目标方法的执行
让我们通过一个完整的日志切面示例来理解AOP:
// 定义切面
@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();
Object[] args = joinPoint.getArgs();
System.out.println("[LOG] 执行方法: " + methodName +
", 参数: " + Arrays.toString(args));
}
// 后置通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[LOG] 方法 " + methodName + " 执行成功, 返回: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[ERROR] 方法 " + methodName + " 执行异常: " + ex.getMessage());
}
// 环绕通知
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
System.out.println("[PERF] 方法执行耗时: " + duration + "ms");
return result;
} catch (Exception e) {
long duration = System.currentTimeMillis() - start;
System.out.println("[ERROR] 方法执行失败,耗时: " + duration + "ms");
throw e;
}
}
}
2.2 Spring事务管理
Spring提供了强大的事务管理抽象,支持声明式事务和编程式事务。声明式事务通过AOP实现,是最常用的方式。
声明式事务示例:
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final InventoryRepository inventoryRepository;
@Autowired
public OrderService(OrderRepository orderRepository,
InventoryRepository inventoryRepository) {
this.orderRepository = orderRepository;
this.inventoryRepository = inventoryRepository;
}
@Transactional
public void createOrder(Order order) {
// 1. 保存订单
orderRepository.save(order);
// 2. 扣减库存
inventoryRepository.decreaseStock(order.getProductId(), order.getQuantity());
// 如果这里抛出异常,整个事务会回滚
if (order.getQuantity() <= 0) {
throw new IllegalArgumentException("订单数量必须大于0");
}
}
}
事务传播行为:
Spring定义了7种事务传播行为,通过@Transactional(propagation = Propagation.XXX)设置:
- REQUIRED(默认):如果当前存在事务,则加入;否则创建新事务
- REQUIRES_NEW:总是创建新事务,如果当前存在事务,则挂起当前事务
- NESTED:如果当前存在事务,则在嵌套事务中执行;否则创建新事务
- SUPPORTS:如果当前存在事务,则加入;否则以非事务方式执行
- NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则挂起
- MANDATORY:如果当前存在事务,则加入;否则抛出异常
- NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
事务隔离级别:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void updateProduct(Product product) {
// 业务逻辑
}
2.3 Spring事件驱动模型
Spring提供了强大的事件驱动模型,允许组件之间进行松耦合的通信。
自定义事件:
public class OrderCreatedEvent extends ApplicationEvent {
private final Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
public Order getOrder() {
return order;
}
}
事件发布者:
@Service
public class OrderService {
private final ApplicationEventPublisher eventPublisher;
@Autowired
public OrderService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Transactional
public void createOrder(Order order) {
// 保存订单
orderRepository.save(order);
// 发布事件
eventPublisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
事件监听器:
@Component
public class OrderEventListener {
// 异步处理
@Async
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
Order order = event.getOrder();
// 发送邮件通知
sendEmailNotification(order);
// 更新库存
updateInventory(order);
// 记录日志
logOrderCreation(order);
}
// 有序处理
@Order(1)
@EventListener
public void firstHandler(OrderCreatedEvent event) {
System.out.println("第一阶段处理");
}
@Order(2)
@EventListener
public void secondHandler(OrderCreatedEvent event) {
System.out.println("第二阶段处理");
}
}
第三部分:Spring Boot与现代开发
3.1 Spring Boot核心特性
Spring Boot是Spring框架的”约定优于配置”理念的完美体现,它极大地简化了Spring应用的搭建和开发过程。
主要特性:
- 自动配置:根据classpath中的依赖自动配置Spring应用
- 起步依赖:简化Maven/Gradle配置
- 内嵌服务器:无需单独部署Tomcat等服务器
- 生产就绪:提供健康检查、指标等生产特性
- 外部化配置:灵活的配置管理
快速启动示例:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
3.2 Spring Boot自动配置原理
Spring Boot的自动配置基于@EnableAutoConfiguration注解,它通过spring.factories文件加载自动配置类。
自定义自动配置示例:
// 自动配置类
@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.enable", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(DataSourceProperties.class)
public class MyDataSourceAutoConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
在src/main/resources/META-INF/spring.factories中配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyDataSourceAutoConfiguration
3.3 Spring Boot Actuator
Actuator提供了生产环境监控和管理的端点:
# application.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,env
endpoint:
health:
show-details: always
常用端点:
/actuator/health:应用健康状态/actuator/info:应用信息/actuator/metrics:应用指标/actuator/env:环境变量
第四部分:Spring Data数据访问
4.1 Spring Data JPA
Spring Data JPA极大地简化了数据库访问层的开发。
实体类定义:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String email;
@Column(name = "created_at")
private LocalDateTime createdAt;
// Getters and setters
}
Repository接口:
public interface UserRepository extends JpaRepository<User, Long> {
// 方法名查询
Optional<User> findByUsername(String username);
// JPQL查询
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email);
// 原生SQL查询
@Query(value = "SELECT * FROM users WHERE created_at > :date", nativeQuery = true)
List<User> findUsersCreatedAfter(@Param("date") LocalDateTime date);
// 分页查询
Page<User> findByUsernameContaining(String username, Pageable pageable);
// 自定义查询
@Modifying
@Query("UPDATE User u SET u.email = :email WHERE u.id = :id")
int updateEmail(@Param("id") Long id, @Param("email") String email);
}
使用示例:
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Transactional
public User createUser(String username, String email) {
User user = new User();
user.setUsername(username);
user.setEmail(email);
user.setCreatedAt(LocalDateTime.now());
return userRepository.save(user);
}
public Optional<User> findByUsername(String username) {
return userRepository.findByUsername(username);
}
public List<User> searchUsers(String keyword, int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
return userRepository.findByUsernameContaining(keyword, pageable).getContent();
}
}
4.2 Spring Data MongoDB
对于NoSQL数据库,Spring Data同样提供了优雅的支持:
// MongoDB实体
@Document(collection = "products")
public class Product {
@Id
private String id;
private String name;
private BigDecimal price;
private String category;
private List<String> tags;
// Getters and setters
}
// Repository
public interface ProductRepository extends MongoRepository<Product, String> {
List<Product> findByCategory(String category);
List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
@Query("{ 'tags': { $in: ?0 } }")
List<Product> findByTagsIn(List<String> tags);
}
第五部分:Spring Security安全框架
5.1 基础配置
Spring Security提供了全面的安全解决方案:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.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()
)
.csrf(csrf -> csrf.ignoringRequestMatchers("/api/**"));
return http.build();
}
@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("admin"))
.roles("ADMIN", "USER")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
5.2 JWT认证
在前后端分离应用中,通常使用JWT进行认证:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenProvider tokenProvider;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = getTokenFromRequest(request);
if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
String username = tokenProvider.getUsername(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
private String getTokenFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
第六部分:Spring Cloud微服务架构
6.1 服务注册与发现(Eureka)
# Eureka Server配置
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka/
// Eureka Client
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductRepository repository;
@GetMapping("/{id}")
public Product getProduct(@PathVariable String id) {
return repository.findById(id).orElseThrow(() -> new RuntimeException("Product not found"));
}
}
6.2 服务网关(Spring Cloud Gateway)
# Gateway配置
spring:
cloud:
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
filters:
- StripPrefix=1
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
- name: Retry
args:
retries: 3
backoff:
firstBackoff: 50ms
maxBackoff: 500ms
factor: 2
basedOnPreviousValue: false
6.3 配置中心(Spring Cloud Config)
# Config Server配置
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/example/config-repo
search-paths: '{application}'
username: ${GIT_USERNAME}
password: ${GIT_PASSWORD}
第七部分:性能优化与最佳实践
7.1 缓存策略
Spring Cache抽象提供了统一的缓存接口:
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory())
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())))
.build();
return redisCacheManager;
}
}
@Service
public class ProductService {
@Cacheable(value = "products", key = "#id")
public Product getProductById(String id) {
// 数据库查询
return productRepository.findById(id).orElse(null);
}
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
return productRepository.save(product);
}
@CacheEvict(value = "products", key = "#id")
public void deleteProduct(String id) {
productRepository.deleteById(id);
}
}
7.2 异步处理
@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;
}
}
@Service
public class NotificationService {
@Async
public void sendEmail(String to, String subject, String body) {
// 模拟耗时操作
try {
Thread.sleep(1000);
System.out.println("邮件已发送到: " + to);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
7.3 监控与日志
// 使用Micrometer进行监控
@Service
public class OrderService {
private final MeterRegistry meterRegistry;
private final Counter orderCounter;
private final Timer orderTimer;
@Autowired
public OrderService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.orderCounter = Counter.builder("orders.created")
.description("Total orders created")
.register(meterRegistry);
this.orderTimer = Timer.builder("order.processing.time")
.description("Time taken to process orders")
.register(meterRegistry);
}
@Transactional
public void createOrder(Order order) {
orderTimer.record(() -> {
orderRepository.save(order);
orderCounter.increment();
});
}
}
第八部分:企业级应用实战案例
8.1 电商系统架构设计
// 用户服务
@Service
public class UserService {
// 用户注册、登录、信息管理
}
// 商品服务
@Service
public class ProductService {
// 商品管理、库存管理
}
// 订单服务
@Service
public class OrderService {
// 订单创建、支付、状态管理
}
// 支付服务
@Service
public class PaymentService {
// 支付处理、对账
}
8.2 分布式事务解决方案
// 使用Seata实现分布式事务
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryClient inventoryClient;
@Autowired
private PaymentClient paymentClient;
@GlobalTransactional // Seata全局事务注解
public Order createDistributedOrder(Order order) {
// 1. 创建订单
orderRepository.save(order);
// 2. 扣减库存(调用库存服务)
inventoryClient.decreaseStock(order.getProductId(), order.getQuantity());
// 3. 创建支付(调用支付服务)
paymentClient.createPayment(order);
return order;
}
}
总结
Spring框架作为Java企业级开发的基石,通过IoC、AOP等核心概念,以及Spring Boot、Spring Cloud等生态系统,为开发者提供了强大而灵活的工具。掌握Spring不仅需要理解其核心原理,更需要在实际项目中不断实践和优化。
从基础的依赖注入到复杂的微服务架构,从简单的CRUD操作到高性能的缓存策略,Spring都能提供优雅的解决方案。随着云原生和响应式编程的兴起,Spring也在不断演进,Spring WebFlux等新技术为构建高性能、高并发的应用提供了新的可能。
学习Spring是一个持续的过程,建议从实际项目出发,逐步深入,最终达到精通的境界。
