引言:为什么选择Spring框架?

Spring框架是Java企业级应用开发的事实标准,它不仅仅是一个框架,更是一套完整的生态系统。从简单的独立应用到复杂的分布式系统,Spring提供了全方位的解决方案。作为Java开发者,掌握Spring意味着掌握了构建现代化、高性能、可维护应用的关键技能。

Spring的核心价值在于其”轻量级”和”非侵入式”的设计理念。与传统的EJB(Enterprise Java Beans)相比,Spring不需要依赖特定的容器,可以运行在任何Java环境中。更重要的是,Spring通过依赖注入(DI)和面向切面编程(AOP)等技术,实现了业务逻辑与基础设施的解耦,让开发者能够专注于业务价值的创造。

第一部分:Spring基础入门

1.1 Spring框架概述

Spring框架是一个分层架构,它由大约20个模块组成,这些模块可以分为几个核心部分:

  • 核心容器(Core Container):包括Spring Core、Spring Beans、Spring Context和Spring Expression Language(SPEL)
  • AOP(Aspect-Oriented Programming):提供了面向切面编程的实现
  • 数据访问/集成(Data Access/Integration):包括JDBC、ORM、OXM、JMS和事务管理
  • Web:包括Web、Web-Servlet、Web-Portlet和Web-WebSocket
  • 测试(Test):提供了对单元测试和集成测试的支持

1.2 依赖注入(DI)详解

依赖注入是Spring框架的核心机制,它实现了对象之间依赖关系的解耦。Spring提供了三种主要的依赖注入方式:

构造器注入(Constructor Injection)

构造器注入是最推荐的方式,因为它保证了对象在创建时就具备了所有必需的依赖。

// 定义服务接口
public interface UserService {
    void saveUser(String username);
}

// 实现服务接口
@Service
public class UserServiceImpl implements UserService {
    private final UserRepository userRepository;
    
    // 使用构造器注入
    @Autowired
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    @Override
    public void saveUser(String username) {
        userRepository.save(username);
    }
}

// 数据访问层
@Repository
public class UserRepository {
    public void save(String username) {
        System.out.println("保存用户: " + username);
    }
}

Setter方法注入(Setter Injection)

Setter注入适用于可选依赖的场景。

@Service
public class OrderService {
    private PaymentService paymentService;
    
    // Setter方法注入
    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
    
    public void processOrder(Order order) {
        paymentService.processPayment(order.getAmount());
    }
}

字段注入(Field Injection)

虽然字段注入代码简洁,但不推荐在生产环境中使用,因为它不利于单元测试和依赖关系的明确性。

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;
    
    @Autowired
    private CategoryRepository categoryRepository;
    
    public Product createProduct(String name, String category) {
        // 业务逻辑
        return productRepository.save(new Product(name, category));
    }
}

1.3 Spring Bean的作用域

Spring Bean支持多种作用域,每种作用域适用于不同的场景:

  • Singleton(单例):默认作用域,每个Spring容器中一个Bean实例
  • Prototype(原型):每次请求都创建新实例
  • Request:每个HTTP请求一个实例(仅在Web应用中有效)
  • Session:每个HTTP会话一个实例(仅在Web应用中有效)
  • Global Session:全局HTTP会话(仅在Portlet应用中有效)
@Component
@Scope("prototype") // 原型作用域
public class PrototypeBean {
    private final String id = UUID.randomUUID().toString();
    
    public String getId() {
        return id;
    }
}

@Component
@Scope("singleton") // 单例作用域(默认)
public class SingletonBean {
    private final String id = UUID.randomUUID().toString();
    
    public String getId() {
        return id;
    }
}

1.4 Spring配置方式

Spring支持多种配置方式,包括XML配置、注解配置和Java配置。

XML配置方式(传统方式)

<!-- 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"
       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"/>
    
    <!-- Bean定义 -->
    <bean id="userService" class="com.example.service.UserServiceImpl"/>
    
    <!-- 构造器注入 -->
    <bean id="orderService" class="com.example.service.OrderService">
        <constructor-arg ref="paymentService"/>
    </bean>
</beans>

注解配置方式(推荐)

// 主配置类
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // 可以在这里定义额外的Bean
}

// 使用配置类
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);
        userService.saveUser("张三");
    }
}

第二部分:Spring核心原理深入

2.1 IoC容器的工作原理

IoC(Inversion of Control)容器是Spring框架的核心。它负责创建、配置和管理Bean的整个生命周期。

BeanFactory vs ApplicationContext

  • BeanFactory:最基础的IoC容器,提供基本的DI功能
  • ApplicationContext:BeanFactory的子接口,提供了更多企业级功能
// BeanFactory示例
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
UserService service = factory.getBean(UserService.class);

// ApplicationContext示例(推荐)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = context.getBean(UserService.class);

Bean的生命周期

Spring Bean的生命周期包含以下步骤:

  1. 实例化:通过构造器或工厂方法创建Bean实例
  2. 属性填充:设置Bean的属性值
  3. 初始化前:调用BeanNameAware、BeanFactoryAware等Aware接口方法
  4. 初始化:调用InitializingBean的afterPropertiesSet方法或自定义init方法
  5. 初始化后:调用BeanPostProcessor的postProcessAfterInitialization方法
  6. 使用:Bean已就绪,可以被应用使用
  7. 销毁:调用DisposableBean的destroy方法或自定义destroy方法
@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
    
    public LifecycleBean() {
        System.out.println("1. 构造器被调用");
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("3. InitializingBean.afterPropertiesSet()被调用");
    }
    
    @PreDestroy
    public void customDestroy() {
        System.out.println("7. @PreDestroy方法被调用");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("6. DisposableBean.destroy()被调用");
    }
    
    @PostConstruct
    public void customInit() {
        System.out.println("2. @PostConstruct方法被调用");
    }
    
    public void initMethod() {
        System.out.println("4. 自定义init-method被调用");
    }
    
    public void destroyMethod() {
        System5. 自定义destroy-method被调用");
    }
}

2.2 依赖注入的实现机制

Spring通过Java反射机制和配置元数据来实现依赖注入。主要的实现方式包括:

构造器注入的解析过程

当Spring容器启动时,它会:

  1. 扫描指定包下的所有类
  2. 识别带有@Component、@Service等注解的类
  3. 解析构造器参数
  4. 在容器中查找匹配的Bean
  5. 通过反射调用构造器创建实例
// 模拟Spring的构造器注入过程
public class SimpleDIContainer {
    private Map<String, Object> beans = new HashMap<>();
    
    public void registerBean(String name, Object bean) {
        beans.put(name, bean);
    }
    
    public <T> T getBean(Class<T> beanClass) {
        // 查找构造器
        Constructor<?>[] constructors = beanClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            if (constructor.isAnnotationPresent(Autowired.class)) {
                // 获取参数类型
                Class<?>[] paramTypes = constructor.getParameterTypes();
                Object[] params = new Object[paramTypes.length];
                
                // 从容器中获取依赖
                for (int i = 0; i < paramTypes.length; i++) {
                    params[i] = findBeanByType(paramTypes[i]);
                }
                
                // 通过反射创建实例
                try {
                    return (T) constructor.newInstance(params);
                } catch (Exception e) {
                    throw new RuntimeException("Failed to create bean", e);
                }
            }
        }
        return null;
    }
    
    private Object findBeanByType(Class<?> type) {
        return beans.values().stream()
            .filter(bean -> type.isAssignableFrom(bean.getClass()))
            .findFirst()
            .orElse(null);
    }
}

2.3 AOP(面向切面编程)原理

AOP是Spring框架的另一个核心特性,它允许开发者将横切关注点(如日志、事务、安全等)从业务逻辑中分离出来。

AOP核心概念

  • 切面(Aspect):封装了横切关注点的模块
  • 连接点(Join Point):程序执行过程中的某个点(如方法执行)
  • 通知(Advice):切面在特定连接点执行的动作
  • 切入点(Pointcut):匹配连接点的表达式
  • 目标对象(Target):被代理的对象
  • 代理(Proxy):Spring AOP创建的对象,包含目标对象和通知

AOP实现方式

Spring AOP默认使用JDK动态代理(针对接口)和CGLIB(针对类)。

// 定义切面
@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("[LOG] 开始执行方法: " + methodName);
    }
    
    // 后置通知
    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[LOG] 方法执行完成: " + methodName);
    }
    
    // 环绕通知
    @Around("serviceMethods()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed(); // 执行目标方法
        long end = System.currentTimeMillis();
        System.out.println("[LOG] 方法执行耗时: " + (end - start) + "ms");
        return result;
    }
    
    // 异常通知
    @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
    public void logException(JoinPoint joinPoint, Exception ex) {
        System.err.println("[ERROR] 方法执行异常: " + 
                         joinPoint.getSignature().getName() + 
                         ", 异常信息: " + ex.getMessage());
    }
}

// 目标类
@Service
public class CalculatorService {
    public int add(int a, int b) {
        return a + b;
    }
    
    public int divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("除数不能为0");
        }
        return a / b;
    }
}

AOP动态代理原理

Spring AOP的底层是通过动态代理实现的。以下是简化的代理创建过程:

// JDK动态代理示例
public class JdkDynamicProxy implements InvocationHandler {
    private Object target;
    
    public JdkDynamicProxy(Object target) {
        this.target = target;
    }
    
    public Object getProxy() {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置通知
        System.out.println("Before: " + method.getName());
        
        // 执行目标方法
        Object result = method.invoke(target, args);
        
        // 后置通知
        System.out.println("After: " + method.getName());
        
        return result;
    }
}

// 使用示例
public class AopDemo {
    public static void main(String[] args) {
        CalculatorService target = new CalculatorService();
        JdkDynamicProxy proxy = new JdkDynamicProxy(target);
        CalculatorService proxyInstance = (CalculatorService) proxy.getProxy();
        
        proxyInstance.add(1, 2); // 会被代理拦截
    }
}

第三部分:Spring Boot实战应用

3.1 Spring Boot快速入门

Spring Boot是Spring框架的”脚手架”,它简化了Spring应用的配置和部署过程。

创建第一个Spring Boot应用

// 主应用类
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

// Web控制器
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    // GET请求:查询用户
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return ResponseEntity.ok(user);
    }
    
    // POST请求:创建用户
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User savedUser = userService.saveUser(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
    }
    
    // PUT请求:更新用户
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        User updatedUser = userService.updateUser(user);
        return ResponseEntity.ok(updatedUser);
    }
    
    // DELETE请求:删除用户
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.noContent().build();
    }
}

// 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String username;
    private String email;
}

配置文件 application.yml

server:
  port: 8080
  servlet:
    context-path: /demo

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/demo_db
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect
        format_sql: true

logging:
  level:
    com.example: DEBUG
    org.hibernate.SQL: DEBUG

3.2 Spring Data JPA实战

Spring Data JPA极大简化了数据库操作,通过简单的接口定义就能实现复杂的CRUD操作。

实体类定义

// 用户实体
@Entity
@Table(name = "users")
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true, length = 50)
    private String username;
    
    @Column(nullable = false, length = 100)
    private String email;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @PrePersist
    public void prePersist() {
        this.createdAt = LocalDateTime.now();
    }
}

// 订单实体(一对多关系)
@Entity
@Table(name = "orders")
@Data
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private BigDecimal amount;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
    
    @Column(name = "order_date")
    private LocalDateTime orderDate;
    
    @PrePersist
    public void prePersist() {
        this.orderDate = LocalDateTime.now();
    }
}

// 枚举类
public enum OrderStatus {
    PENDING, PROCESSING, COMPLETED, CANCELLED
}

Repository接口定义

// 用户Repository
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
    
    // 自定义查询方法:根据用户名查询
    Optional<User> findByUsername(String username);
    
    // 自定义查询方法:根据邮箱查询
    Optional<User> findByEmail(String email);
    
    // 复杂查询:用户名包含指定字符串
    List<User> findByUsernameContaining(String keyword);
    
    // 分页查询
    Page<User> findByUsernameContaining(String keyword, Pageable pageable);
    
    // 自定义JPQL查询
    @Query("SELECT u FROM User u WHERE u.email LIKE %:keyword%")
    List<User> findByEmailKeyword(@Param("keyword") String keyword);
    
    // 原生SQL查询
    @Query(value = "SELECT * FROM users WHERE created_at > :date", nativeQuery = true)
    List<User> findUsersCreatedAfter(@Param("date") LocalDateTime date);
    
    // 自定义更新操作
    @Modifying
    @Query("UPDATE User u SET u.email = :email WHERE u.id = :id")
    int updateUserEmail(@Param("id") Long id, @Param("email") String email);
    
    // 复杂查询:自定义返回类型
    @Query("SELECT new com.example.dto.UserSummary(u.id, u.username, COUNT(o)) " +
           "FROM User u LEFT JOIN u.orders o GROUP BY u.id, u.username")
    List<UserSummary> findUserOrderCount();
}

// 订单Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    
    // 根据用户查询订单
    List<Order> findByUser(User user);
    
    // 根据状态查询
    List<Order> findByStatus(OrderStatus status);
    
    // 复杂查询:查询指定用户的指定状态订单
    @Query("SELECT o FROM Order o WHERE o.user.id = :userId AND o.status = :status")
    List<Order> findUserOrdersByStatus(@Param("userId") Long userId, 
                                      @Param("status") OrderStatus status);
    
    // 统计查询
    @Query("SELECT COUNT(o) FROM Order o WHERE o.user.id = :userId")
    Long countOrdersByUser(@Param("userId") Long userId);
    
    // 聚合查询
    @Query("SELECT SUM(o.amount) FROM Order o WHERE o.user.id = :userId AND o.status = 'COMPLETED'")
    BigDecimal calculateTotalSpent(@Param("userId") Long userId);
}

Service层实现

// Service接口
public interface UserService {
    User getUserById(Long id);
    User saveUser(User user);
    User updateUser(User user);
    void deleteUser(Long id);
    List<User> getAllUsers();
    Page<User> searchUsers(String keyword, int page, int size);
    User getUserWithOrders(Long id);
}

// Service实现类
@Service
@Transactional
public class UserServiceImpl implements UserService {
    
    private final UserRepository userRepository;
    private final OrderRepository orderRepository;
    
    public UserServiceImpl(UserRepository userRepository, OrderRepository orderRepository) {
        this.userRepository = userRepository;
        this.orderRepository = orderRepository;
    }
    
    @Override
    @Transactional(readOnly = true)
    public User getUserById(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new UserNotFoundException("用户不存在: " + id));
    }
    
    @Override
    public User saveUser(User user) {
        // 业务验证
        if (userRepository.findByUsername(user.getUsername()).isPresent()) {
            throw new IllegalArgumentException("用户名已存在");
        }
        return userRepository.save(user);
    }
    
    @Override
    public User updateUser(User user) {
        User existingUser = getUserById(user.getId());
        existingUser.setUsername(user.getUsername());
        existingUser.setEmail(user.getEmail());
        return userRepository.save(existingUser);
    }
    
    @Override
    public void deleteUser(Long id) {
        User user = getUserById(id);
        // 检查是否有订单关联
        List<Order> orders = orderRepository.findByUser(user);
        if (!orders.isEmpty()) {
            throw new IllegalStateException("无法删除有订单的用户");
        }
        userRepository.delete(user);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<User> searchUsers(String keyword, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
        return userRepository.findByUsernameContaining(keyword, pageable);
    }
    
    @Override
    @Transactional(readOnly = true)
    public User getUserWithOrders(Long id) {
        User user = getUserById(id);
        // 触发懒加载
        user.getOrders().size(); // 确保订单被加载
        return user;
    }
}

3.3 Spring事务管理

Spring的事务管理是其核心功能之一,提供了声明式和编程式两种方式。

声明式事务(推荐)

@Service
public class BankAccountService {
    
    @Autowired
    private AccountRepository accountRepository;
    
    // 默认传播行为:REQUIRED(如果存在事务则加入,否则新建)
    @Transactional
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        Account fromAccount = accountRepository.findById(fromId)
                .orElseThrow(() -> new RuntimeException("转出账户不存在"));
        Account toAccount = accountRepository.findById(toId)
                .orElseThrow(() -> new RuntimeException("转入账户不存在"));
        
        if (fromAccount.getBalance().compareTo(amount) < 0) {
            throw new InsufficientBalanceException("余额不足");
        }
        
        fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
        toAccount.setBalance(toAccount.getBalance().add(amount));
        
        accountRepository.save(fromAccount);
        accountRepository.save(toAccount);
    }
    
    // 传播行为:REQUIRES_NEW(总是新建事务)
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logTransaction(Long fromId, Long toId, BigDecimal amount) {
        // 记录交易日志,独立事务
        TransactionLog log = new TransactionLog();
        log.setFromAccount(fromId);
        log.setToAccount(toId);
        log.setAmount(amount);
        log.setTimestamp(LocalDateTime.now());
        // 保存日志...
    }
    
    // 只读事务(优化性能)
    @Transactional(readOnly = true)
    public Account getAccount(Long id) {
        return accountRepository.findById(id).orElse(null);
    }
    
    // 指定回滚异常
    @Transactional(rollbackFor = {Exception.class})
    public void complexOperation() throws Exception {
        // 业务逻辑...
        // 只有在抛出指定异常时才回滚
    }
}

编程式事务

@Service
public class ProgrammaticTransactionService {
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    public void executeWithTransaction() {
        TransactionTemplate template = new TransactionTemplate(transactionManager);
        template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        
        template.execute(status -> {
            try {
                // 业务逻辑
                return null;
            } catch (Exception e) {
                status.setRollbackOnly(); // 标记回滚
                throw e;
            }
        });
    }
}

3.4 Spring Security集成

Spring Security是Spring生态系统的安全框架,提供了全面的安全解决方案。

基础配置

@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() // 其他接口需要认证
            )
            .httpBasic(Customizer.withDefaults()) // 基础认证
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态
            );
        
        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);
    }
}

JWT认证实现

// JWT工具类
@Component
public class JwtUtil {
    @Value("${jwt.secret}")
    private String secret;
    
    @Value("${jwt.expiration}")
    private Long expiration;
    
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("roles", userDetails.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList()));
        
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }
    
    public String extractUsername(String token) {
        return getClaims(token).getSubject();
    }
    
    public boolean validateToken(String token, UserDetails userDetails) {
        final String username = extractUsername(token);
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }
    
    private Claims getClaims(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }
    
    private boolean isTokenExpired(String token) {
        return getClaims(token).getExpiration().before(new Date());
    }
}

// JWT认证过滤器
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                   HttpServletResponse response, 
                                   FilterChain filterChain) throws ServletException, IOException {
        
        final String authHeader = request.getHeader("Authorization");
        
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }
        
        final String jwt = authHeader.substring(7);
        final String username = jwtUtil.extractUsername(jwt);
        
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            
            if (jwtUtil.validateToken(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken authentication = 
                    new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        
        filterChain.doFilter(request, response);
    }
}

3.5 REST API开发最佳实践

统一响应格式

// 统一响应体
@Data
@Builder
public class ApiResponse<T> {
    private boolean success;
    private String message;
    private T data;
    private Long timestamp;
    
    public static <T> ApiResponse<T> success(T data) {
        return ApiResponse.<T>builder()
                .success(true)
                .data(data)
                .timestamp(System.currentTimeMillis())
                .build();
    }
    
    public static <T> ApiResponse<T> error(String message) {
        return ApiResponse.<T>builder()
                .success(false)
                .message(message)
                .timestamp(System.currentTimeMillis())
                .build();
    }
}

// 全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(UserNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ApiResponse<String> handleUserNotFound(UserNotFoundException ex) {
        return ApiResponse.error(ex.getMessage());
    }
    
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResponse<String> handleIllegalArgument(IllegalArgumentException ex) {
        return ApiResponse.error(ex.getMessage());
    }
    
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResponse<String> handleGenericException(Exception ex) {
        return ApiResponse.error("服务器内部错误");
    }
}

分页查询实现

// 分页请求DTO
@Data
public class PageRequestDTO {
    @Min(0)
    private int page = 0;
    
    @Min(1)
    @Max(100)
    private int size = 20;
    
    private String sortBy = "id";
    
    private boolean asc = true;
    
    public Pageable toPageable() {
        Sort sort = asc ? Sort.by(sortBy).ascending() : Sort.by(sortBy).descending();
        return PageRequest.of(page, size, sort);
    }
}

// 分页响应DTO
@Data
@Builder
public class PageResponseDTO<T> {
    private List<T> content;
    private int page;
    private int size;
    private long totalElements;
    private int totalPages;
    private boolean last;
    private boolean first;
    
    public static <T> PageResponseDTO<T> of(Page<T> page) {
        return PageResponseDTO.<T>builder()
                .content(page.getContent())
                .page(page.getNumber())
                .size(page.getSize())
                .totalElements(page.getTotalElements())
                .totalPages(page.getTotalPages())
                .last(page.isLast())
                .first(page.isFirst())
                .build();
    }
}

// Controller使用
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping
    public ApiResponse<PageResponseDTO<User>> getUsers(PageRequestDTO pageRequest) {
        Page<User> userPage = userService.searchUsers("", pageRequest.toPageable());
        return ApiResponse.success(PageResponseDTO.of(userPage));
    }
}

第四部分:Spring高级特性

4.1 Spring事件驱动编程

Spring提供了强大的事件发布-订阅机制,用于组件间的解耦通信。

自定义事件

// 自定义事件类
public class UserRegisteredEvent extends ApplicationEvent {
    private final User user;
    
    public UserRegisteredEvent(Object source, User user) {
        super(source);
        this.user = user;
    }
    
    public User getUser() {
        return user;
    }
}

// 事件发布者
@Service
public class UserService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    @Autowired
    private UserRepository userRepository;
    
    public User registerUser(User user) {
        User savedUser = userRepository.save(user);
        // 发布事件
        eventPublisher.publishEvent(new UserRegisteredEvent(this, savedUser));
        return savedUser;
    }
}

// 事件监听器(同步)
@Component
public class UserRegistrationListener {
    
    @EventListener
    public void handleUserRegistration(UserRegisteredEvent event) {
        System.out.println("用户注册事件收到: " + event.getUser().getUsername());
        // 发送欢迎邮件
        sendWelcomeEmail(event.getUser());
    }
    
    private void sendWelcomeEmail(User user) {
        // 模拟发送邮件
        System.out.println("发送欢迎邮件到: " + user.getEmail());
    }
}

// 异步事件监听器
@Component
public class AsyncEventListener {
    
    @Async // 使用异步处理
    @EventListener
    public void handleAsyncEvent(UserRegisteredEvent event) {
        System.out.println("异步处理用户注册: " + event.getUser().getUsername());
        // 耗时操作,如发送通知、更新统计等
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

// 异步配置
@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;
    }
}

4.2 Spring缓存抽象

Spring Cache提供了统一的缓存抽象,支持多种缓存实现。

// 缓存配置
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager() {
        // 使用Caffeine作为缓存实现
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .maximumSize(1000)
                .recordStats());
        return cacheManager;
    }
}

// 缓存服务
@Service
public class ProductService {
    
    @Autowired
    private ProductRepository productRepository;
    
    // 缓存查询结果
    @Cacheable(value = "products", key = "#id")
    public Product getProductById(Long id) {
        System.out.println("从数据库查询产品: " + id);
        return productRepository.findById(id).orElse(null);
    }
    
    // 更新缓存
    @CachePut(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        System.out.println("更新产品: " + product.getId());
        return productRepository.save(product);
    }
    
    // 删除缓存
    @CacheEvict(value = "products", key = "#id")
    public void deleteProduct(Long id) {
        System.out.println("删除产品: " + id);
        productRepository.deleteById(id);
    }
    
    // 复杂缓存逻辑
    @Cacheable(value = "products", key = "#category", unless = "#result == null")
    public List<Product> getProductsByCategory(String category) {
        System.out.println("按类别查询产品: " + category);
        return productRepository.findByCategory(category);
    }
}

4.3 Spring定时任务

Spring提供了强大的定时任务支持,基于cron表达式。

@Configuration
@EnableScheduling
public class SchedulerConfig {
    // 定时任务示例
}

@Component
public class ScheduledTasks {
    
    // 固定延迟任务(每5秒执行一次)
    @Scheduled(fixedDelay = 5000)
    public void fixedDelayTask() {
        System.out.println("固定延迟任务执行: " + new Date());
    }
    
    // 固定频率任务(每5秒执行一次)
    @Scheduled(fixedRate = 5000)
    public void fixedRateTask() {
        System.out.println("固定频率任务执行: " + new Date());
    }
    
    // Cron表达式任务(每天凌晨2点执行)
    @Scheduled(cron = "0 0 2 * * ?")
    public void dailyTask() {
        System.out.println("每日任务执行: " + new Date());
        // 清理过期数据、生成报表等
    }
    
    // 带参数的任务
    @Scheduled(cron = "0 */15 * * * ?") // 每15分钟执行
    public void scheduledWithParams() {
        System.out.println("每15分钟执行的任务: " + new Date());
        // 检查系统状态、发送通知等
    }
    
    // 动态cron表达式
    @Scheduled(cron = "#{@cronExpression}")
    public void dynamicCronTask() {
        System.out.println("动态cron任务执行: " + new Date());
    }
    
    @Bean
    public String cronExpression() {
        // 可以从配置中心读取
        return "0 0/5 * * * ?"; // 每5分钟执行
    }
}

4.4 Spring测试框架

Spring提供了强大的测试支持,包括单元测试和集成测试。

单元测试

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;
    
    @Mock
    private OrderRepository orderRepository;
    
    @InjectMocks
    private UserServiceImpl userService;
    
    @Test
    void shouldReturnUserWhenUserExists() {
        // Given
        User mockUser = new User(1L, "testuser", "test@example.com");
        when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));
        
        // When
        User result = userService.getUserById(1L);
        
        // Then
        assertNotNull(result);
        assertEquals("testuser", result.getUsername());
        verify(userRepository, times(1)).findById(1L);
    }
    
    @Test
    void shouldThrowExceptionWhenUserNotFound() {
        // Given
        when(userRepository.findById(999L)).thenReturn(Optional.empty());
        
        // When & Then
        assertThrows(UserNotFoundException.class, () -> {
            userService.getUserById(999L);
        });
    }
}

集成测试

@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.yml")
@Transactional
class UserServiceIntegrationTest {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    void shouldSaveAndRetrieveUser() {
        // Given
        User user = new User(null, "integrationtest", "test@example.com");
        
        // When
        User savedUser = userService.saveUser(user);
        User foundUser = userService.getUserById(savedUser.getId());
        
        // Then
        assertNotNull(savedUser.getId());
        assertEquals("integrationtest", foundUser.getUsername());
    }
    
    @Test
    void shouldRollbackOnException() {
        // Given
        User user = new User(null, "rollbacktest", "test@example.com");
        
        // When & Then
        assertThrows(RuntimeException.class, () -> {
            userService.saveUser(user);
            throw new RuntimeException("Simulated error");
        });
        
        // 验证事务回滚
        List<User> users = userService.getAllUsers();
        assertTrue(users.stream().noneMatch(u -> "rollbacktest".equals(u.getUsername())));
    }
}

// Web层集成测试
@WebMvcTest(UserController.class)
class UserControllerWebTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private UserService userService;
    
    @Test
    void shouldReturnUserWhenExists() throws Exception {
        // Given
        User user = new User(1L, "testuser", "test@example.com");
        when(userService.getUserById(1L)).thenReturn(user);
        
        // When & Then
        mockMvc.perform(get("/api/users/1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.username").value("testuser"));
    }
}

第五部分:Spring生态系统与微服务

5.1 Spring Cloud微服务架构

Spring Cloud为分布式系统开发提供了一站式解决方案。

服务注册与发现(Eureka)

// Eureka Server(注册中心)
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

// Eureka Client(服务提供者)
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceProviderApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }
    
    @Value("${server.port}")
    private int port;
    
    @GetMapping("/service")
    public String service() {
        return "Hello from service on port " + port;
    }
}

服务调用(Feign)

// Feign客户端
@FeignClient(name = "service-provider")
public interface ServiceProviderClient {
    
    @GetMapping("/service")
    String getService();
}

// 使用Feign
@Service
public class ConsumerService {
    
    @Autowired
    private ServiceProviderClient client;
    
    public String callService() {
        return client.getService();
    }
}

配置中心(Config Server)

// Config Server
@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: '{application}'

5.2 Spring Boot Actuator监控

Actuator提供了生产级别的应用监控和管理功能。

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env,loggers
  endpoint:
    health:
      show-details: always
  metrics:
    tags:
      application: myapp
// 自定义健康检查
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
    
    @Autowired
    private DataSource dataSource;
    
    @Override
    public Health health() {
        try (Connection connection = dataSource.getConnection()) {
            return Health.up()
                    .withDetail("database", "MySQL")
                    .withDetail("version", connection.getMetaData().getDatabaseProductVersion())
                    .build();
        } catch (Exception e) {
            return Health.down()
                    .withDetail("error", e.getMessage())
                    .build();
        }
    }
}

第六部分:性能优化与最佳实践

6.1 连接池优化

// HikariCP配置
@Configuration
public class DataSourceConfig {
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public HikariDataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/demo");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        
        // 连接池配置
        dataSource.setMaximumPoolSize(20);
        dataSource.setMinimumIdle(5);
        dataSource.setConnectionTimeout(30000);
        dataSource.setIdleTimeout(600000);
        dataSource.setMaxLifetime(1800000);
        dataSource.setLeakDetectionThreshold(60000);
        
        return dataSource;
    }
}

6.2 异步处理优化

@Configuration
@EnableAsync
public class AsyncConfig {
    
    @Bean(name = "taskExecutor")
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("Async-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

@Service
public class AsyncService {
    
    @Async("taskExecutor")
    public CompletableFuture<String> processAsync(String data) {
        // 模拟耗时操作
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return CompletableFuture.completedFuture("Processed: " + data);
    }
}

6.3 JVM调优建议

# JVM参数配置示例
# 在application.yml或启动脚本中配置
# -Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

第七部分:实战项目示例

7.1 完整的REST API项目结构

src/main/java/com/example/demo/
├── DemoApplication.java
├── config/
│   ├── AppConfig.java
│   ├── SecurityConfig.java
│   └── AsyncConfig.java
├── controller/
│   ├── UserController.java
│   ├── OrderController.java
│   └── ProductController.java
├── service/
│   ├── UserService.java
│   ├── OrderService.java
│   └── ProductService.java
├── repository/
│   ├── UserRepository.java
│   ├── OrderRepository.java
│   └── ProductRepository.java
├── entity/
│   ├── User.java
│   ├── Order.java
│   └── Product.java
├── dto/
│   ├── request/
│   │   ├── UserCreateRequest.java
│   │   └── OrderCreateRequest.java
│   └── response/
│       ├── UserResponse.java
│       ├── OrderResponse.java
│       └── ApiResponse.java
├── exception/
│   ├── UserNotFoundException.java
│   └── GlobalExceptionHandler.java
└── listener/
    └── UserEventListener.java

7.2 完整的Controller示例

@RestController
@RequestMapping("/api/v1")
@Validated
public class UserController {
    
    private final UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    @GetMapping("/users/{id}")
    public ResponseEntity<ApiResponse<UserResponse>> getUser(@PathVariable @Min(1) Long id) {
        User user = userService.getUserById(id);
        UserResponse response = UserResponse.from(user);
        return ResponseEntity.ok(ApiResponse.success(response));
    }
    
    @PostMapping("/users")
    public ResponseEntity<ApiResponse<UserResponse>> createUser(
            @Valid @RequestBody UserCreateRequest request) {
        User user = request.toEntity();
        User savedUser = userService.saveUser(user);
        UserResponse response = UserResponse.from(savedUser);
        return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.success(response));
    }
    
    @GetMapping("/users")
    public ResponseEntity<ApiResponse<PageResponseDTO<UserResponse>>> getUsers(
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @RequestParam(defaultValue = "10") @Min(1) @Max(100) int size,
            @RequestParam(defaultValue = "id") String sortBy,
            @RequestParam(defaultValue = "true") boolean asc) {
        
        PageRequestDTO pageRequest = new PageRequestDTO();
        pageRequest.setPage(page);
        pageRequest.setSize(size);
        pageRequest.setSortBy(sortBy);
        pageRequest.setAsc(asc);
        
        Page<User> userPage = userService.searchUsers("", pageRequest.toPageable());
        PageResponseDTO<UserResponse> response = PageResponseDTO.of(
                userPage.map(UserResponse::from));
        
        return ResponseEntity.ok(ApiResponse.success(response));
    }
    
    @PutMapping("/users/{id}")
    public ResponseEntity<ApiResponse<UserResponse>> updateUser(
            @PathVariable Long id,
            @Valid @RequestBody UserCreateRequest request) {
        User user = request.toEntity();
        user.setId(id);
        User updatedUser = userService.updateUser(user);
        UserResponse response = UserResponse.from(updatedUser);
        return ResponseEntity.ok(ApiResponse.success(response));
    }
    
    @DeleteMapping("/users/{id}")
    public ResponseEntity<ApiResponse<Void>> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.ok(ApiResponse.success(null));
    }
}

总结

Spring框架作为Java企业级开发的基石,其生态系统庞大而完善。从基础的IoC容器到复杂的微服务架构,Spring提供了全方位的解决方案。掌握Spring不仅需要理解其核心原理,更需要在实际项目中不断实践和优化。

学习Spring的建议路径:

  1. 基础阶段:深入理解IoC、DI、AOP等核心概念
  2. 进阶阶段:掌握Spring Boot、Spring Data JPA、Spring Security
  3. 高级阶段:学习Spring Cloud、响应式编程、性能调优
  4. 实战阶段:参与实际项目,积累经验

记住,Spring不仅仅是一个框架,它代表了一种现代化的软件开发理念:约定优于配置、组件化、解耦和可维护性。通过不断学习和实践,你将能够运用Spring构建出高质量的企业级应用。