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

在Java企业级开发领域,Spring框架已经成为事实上的标准。根据2023年Stack Overflow开发者调查,Spring框架在最受欢迎的Java框架中稳居榜首,超过70%的Java开发者在工作中使用Spring。Spring不仅仅是一个框架,它是一个完整的生态系统,涵盖了从依赖注入到微服务架构的方方面面。

Spring框架的核心优势在于其控制反转(IoC)面向切面编程(AOP)的设计理念。通过IoC容器管理对象生命周期,通过AOP实现横切关注点的分离,Spring让开发者能够专注于业务逻辑,而不是基础设施代码。此外,Spring Boot的出现极大地简化了Spring应用的配置和部署,使得从零开始构建一个生产级应用变得前所未有的简单。

第一部分:Spring核心概念详解

1.1 控制反转(IoC)与依赖注入(DI)

控制反转(Inversion of Control, IoC) 是Spring框架的基石。传统的编程模式中,对象负责创建和管理其依赖的对象。而在IoC模式下,对象的创建和依赖关系的管理由外部容器(Spring IoC容器)负责。

依赖注入(Dependency Injection, DI) 是实现IoC的具体方式。Spring通过三种主要方式实现依赖注入:

  1. 构造器注入(Constructor Injection)
  2. Setter方法注入(Setter Injection)
  3. 字段注入(Field Injection)

示例:构造器注入的实现

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

// 2. 实现服务接口
@Service
public class UserServiceImpl implements UserService {
    private final UserRepository userRepository;
    
    // 使用构造器注入
    @Autowired
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    @Override
    public void saveUser(String username) {
        // 业务逻辑
        System.out.println("Saving user: " + username);
        userRepository.save(username);
    }
}

// 3. 定义数据访问层
@Repository
public class UserRepository {
    public void save(String username) {
        // 模拟数据库操作
        System.out.println("Database: User " + username + " saved");
    }
}

// 4. 主应用类
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        
        // 从容器中获取Bean
        UserService userService = context.getBean(UserService.class);
        userService.saveUser("John Doe");
        
        context.close();
    }
}

代码解析:

  • @Service@Repository 注解将类标记为Spring Bean
  • @Autowired 注解告诉Spring自动注入依赖
  • Spring容器在启动时会创建UserServiceImpl实例,并自动注入UserRepository实例
  • 这种方式实现了松耦合,便于单元测试和代码维护

1.2 Spring Bean的生命周期

Spring Bean的生命周期是理解Spring框架的关键。从Bean的创建到销毁,Spring提供了多个扩展点:

实例化 -> 属性赋值 -> 初始化 -> 使用 -> 销毁

示例:自定义Bean生命周期管理

@Component
public class CustomBean implements InitializingBean, DisposableBean {
    
    public CustomBean() {
        System.out.println("1. 构造函数调用");
    }
    
    @PostConstruct
    public void postConstruct() {
        System.out.println("3. @PostConstruct注解方法调用");
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("4. InitializingBean.afterPropertiesSet()调用");
    }
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("6. @PreDestroy注解方法调用");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("7. DisposableBean.destroy()调用");
    }
    
    // 自定义初始化方法
    @Bean(initMethod = "customInit")
    public void customInit() {
        System.out.println("5. 自定义init-method调用");
    }
    
    // 自定义销毁方法
    @Bean(destroyMethod = "customDestroy")
    public void customDestroy() {
        System.out.println("8. 自定义destroy-method调用");
    }
}

生命周期执行顺序:

  1. 构造函数调用
  2. 属性赋值(通过setter或字段)
  3. @PostConstruct注解方法
  4. InitializingBean.afterPropertiesSet()
  5. 自定义init-method
  6. Bean就绪,可以使用
  7. @PreDestroy注解方法
  8. DisposableBean.destroy()
  9. 自定义destroy-method

1.3 面向切面编程(AOP)

AOP允许开发者将横切关注点(如日志、事务、安全)从业务逻辑中分离出来。Spring 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("[LOG] 开始执行方法: " + methodName);
    }
    
    // 后置通知
    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[LOG] 方法执行完成: " + methodName);
    }
    
    // 返回通知
    @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, Throwable ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[LOG] 方法 " + methodName + " 抛出异常: " + ex.getMessage());
    }
    
    // 环绕通知(最强大)
    @Around("serviceMethods()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        System.out.println("[LOG] 环绕通知开始: " + joinPoint.getSignature().getName());
        
        try {
            // 执行目标方法
            Object result = joinPoint.proceed();
            long endTime = System.currentTimeMillis();
            System.out.println("[LOG] 方法执行耗时: " + (endTime - startTime) + "ms");
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            System.out.println("[LOG] 方法执行异常,耗时: " + (endTime - startTime) + "ms");
            throw e;
        }
    }
}

// 2. 业务服务类
@Service
public class OrderService {
    public String createOrder(String orderId) {
        System.out.println("正在创建订单: " + orderId);
        return "Order " + orderId + " created successfully";
    }
    
    public void processOrder(String orderId) {
        System.out.println("正在处理订单: " + orderId);
        if (orderId == null) {
            throw new IllegalArgumentException("订单ID不能为空");
        }
    }
}

// 3. 启用AOP
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // 配置类
}

AOP执行流程:

  1. 环绕通知开始
  2. 前置通知
  3. 执行目标方法
  4. 后置通知
  5. 返回通知(如果正常返回)
  6. 异常通知(如果抛出异常)
  7. 环绕通知结束

第二部分:Spring Boot实战开发

2.1 Spring Boot快速入门

Spring Boot通过约定优于配置的理念,极大地简化了Spring应用的开发。

示例:创建一个简单的REST API

// 1. 项目结构
/*
src/main/java/com/example/demo/
├── DemoApplication.java          # 主启动类
├── controller/
│   └── UserController.java      # 控制器
├── service/
│   └── UserService.java         # 服务层
├── model/
│   └── User.java                # 实体类
└── repository/
    └── UserRepository.java      # 数据访问层
*/

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

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

// 4. 数据访问层(内存数据库)
@Repository
public class UserRepository {
    private final Map<Long, User> users = new ConcurrentHashMap<>();
    private final AtomicLong idGenerator = new AtomicLong(1);
    
    public List<User> findAll() {
        return new ArrayList<>(users.values());
    }
    
    public User findById(Long id) {
        return users.get(id);
    }
    
    public User save(User user) {
        if (user.getId() == null) {
            user.setId(idGenerator.getAndIncrement());
        }
        users.put(user.getId(), user);
        return user;
    }
    
    public void delete(Long id) {
        users.remove(id);
    }
}

// 5. 服务层
@Service
public class UserService {
    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
    
    public User getUserById(Long id) {
        User user = userRepository.findById(id);
        if (user == null) {
            throw new RuntimeException("User not found with id: " + id);
        }
        return user;
    }
    
    public User createUser(User user) {
        return userRepository.save(user);
    }
    
    public User updateUser(Long id, User user) {
        User existingUser = userRepository.findById(id);
        if (existingUser == null) {
            throw new RuntimeException("User not found with id: " + id);
        }
        user.setId(id);
        return userRepository.save(user);
    }
    
    public void deleteUser(Long id) {
        User user = userRepository.findById(id);
        if (user == null) {
            throw new RuntimeException("User not found with id: " + id);
        }
        userRepository.delete(id);
    }
}

// 6. 控制器层
@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        List<User> users = userService.getAllUsers();
        return ResponseEntity.ok(users);
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return ResponseEntity.ok(user);
    }
    
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.createUser(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        User updatedUser = userService.updateUser(id, user);
        return ResponseEntity.ok(updatedUser);
    }
    
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.noContent().build();
    }
}

// 7. 配置文件 application.properties
/*
server.port=8080
spring.application.name=user-service
logging.level.com.example.demo=DEBUG
*/

测试API:

# 创建用户
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"张三","email":"zhangsan@example.com"}'

# 查询所有用户
curl http://localhost:8080/api/users

# 查询单个用户
curl http://localhost:8080/api/users/1

# 更新用户
curl -X PUT http://localhost:8080/api/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name":"张三更新","email":"zhangsan_updated@example.com"}'

# 删除用户
curl -X DELETE http://localhost:8080/api/users/1

2.2 Spring Data JPA与数据库集成

Spring Data JPA提供了对JPA(Java Persistence API)的抽象,使得数据库操作变得极其简单。

示例:使用Spring Data JPA操作MySQL

// 1. 添加依赖(pom.xml)
/*
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
*/

// 2. 实体类
@Entity
@Table(name = "products")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String name;
    
    @Column(nullable = false)
    private BigDecimal price;
    
    @Column(name = "category_id")
    private Long categoryId;
    
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at")
    private Date createdAt;
    
    @PrePersist
    protected void onCreate() {
        this.createdAt = new Date();
    }
}

// 3. Repository接口(无需实现)
public interface ProductRepository extends JpaRepository<Product, Long> {
    
    // 自定义查询方法
    List<Product> findByNameContaining(String name);
    
    List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
    
    List<Product> findByCategoryId(Long categoryId);
    
    // 使用JPQL查询
    @Query("SELECT p FROM Product p WHERE p.price > :minPrice")
    List<Product> findProductsAbovePrice(@Param("minPrice") BigDecimal minPrice);
    
    // 使用原生SQL查询
    @Query(value = "SELECT * FROM products WHERE category_id = :categoryId", nativeQuery = true)
    List<Product> findProductsByCategoryId(@Param("categoryId") Long categoryId);
    
    // 分页查询
    Page<Product> findByPriceBetween(BigDecimal min, BigDecimal max, Pageable pageable);
    
    // 排序查询
    List<Product> findByCategoryIdOrderByPriceDesc(Long categoryId);
}

// 4. 服务层
@Service
@Transactional
public class ProductService {
    private final ProductRepository productRepository;
    
    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
    
    // 创建产品
    public Product createProduct(Product product) {
        return productRepository.save(product);
    }
    
    // 批量创建产品
    public List<Product> createProducts(List<Product> products) {
        return productRepository.saveAll(products);
    }
    
    // 查询所有产品
    public List<Product> getAllProducts() {
        return productRepository.findAll();
    }
    
    // 根据ID查询产品
    public Product getProductById(Long id) {
        return productRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Product not found with id: " + id));
    }
    
    // 根据名称模糊查询
    public List<Product> searchProductsByName(String keyword) {
        return productRepository.findByNameContaining(keyword);
    }
    
    // 根据价格范围查询
    public List<Product> getProductsByPriceRange(BigDecimal min, BigDecimal max) {
        return productRepository.findByPriceBetween(min, max);
    }
    
    // 分页查询
    public Page<Product> getProductsByPage(int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("price").descending());
        return productRepository.findAll(pageable);
    }
    
    // 更新产品
    public Product updateProduct(Long id, Product productDetails) {
        Product product = getProductById(id);
        product.setName(productDetails.getName());
        product.setPrice(productDetails.getPrice());
        product.setCategoryId(productDetails.getCategoryId());
        return productRepository.save(product);
    }
    
    // 删除产品
    public void deleteProduct(Long id) {
        Product product = getProductById(id);
        productRepository.delete(product);
    }
    
    // 统计产品数量
    public long countProducts() {
        return productRepository.count();
    }
    
    // 检查产品是否存在
    public boolean productExists(Long id) {
        return productRepository.existsById(id);
    }
}

// 5. 控制器层
@RestController
@RequestMapping("/api/products")
public class ProductController {
    private final ProductService productService;
    
    public ProductController(ProductService productService) {
        this.productService = productService;
    }
    
    @PostMapping
    public ResponseEntity<Product> createProduct(@RequestBody Product product) {
        Product createdProduct = productService.createProduct(product);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdProduct);
    }
    
    @GetMapping
    public ResponseEntity<List<Product>> getAllProducts() {
        List<Product> products = productService.getAllProducts();
        return ResponseEntity.ok(products);
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        Product product = productService.getProductById(id);
        return ResponseEntity.ok(product);
    }
    
    @GetMapping("/search")
    public ResponseEntity<List<Product>> searchProducts(@RequestParam String keyword) {
        List<Product> products = productService.searchProductsByName(keyword);
        return ResponseEntity.ok(products);
    }
    
    @GetMapping("/price-range")
    public ResponseEntity<List<Product>> getProductsByPriceRange(
            @RequestParam BigDecimal min,
            @RequestParam BigDecimal max) {
        List<Product> products = productService.getProductsByPriceRange(min, max);
        return ResponseEntity.ok(products);
    }
    
    @GetMapping("/page")
    public ResponseEntity<Page<Product>> getProductsByPage(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        Page<Product> products = productService.getProductsByPage(page, size);
        return ResponseEntity.ok(products);
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<Product> updateProduct(@PathVariable Long id, @RequestBody Product product) {
        Product updatedProduct = productService.updateProduct(id, product);
        return ResponseEntity.ok(updatedProduct);
    }
    
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
        productService.deleteProduct(id);
        return ResponseEntity.noContent().build();
    }
    
    @GetMapping("/count")
    public ResponseEntity<Long> countProducts() {
        long count = productService.countProducts();
        return ResponseEntity.ok(count);
    }
}

// 6. 配置文件 application.properties
/*
spring.datasource.url=jdbc:mysql://localhost:3306/spring_demo?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

server.port=8080
logging.level.org.hibernate.SQL=DEBUG
*/

2.3 Spring Security安全集成

Spring Security提供了全面的安全解决方案,包括认证、授权、CSRF保护等。

示例:基于JWT的认证系统

// 1. 添加依赖
/*
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
*/

// 2. JWT工具类
@Component
public class JwtTokenUtil {
    private static final String SECRET_KEY = "your-secret-key-should-be-long-and-secure";
    private static final long EXPIRATION_TIME = 86400000; // 24小时
    
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("authorities", userDetails.getAuthorities());
        
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }
    
    public String extractUsername(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }
    
    public boolean validateToken(String token, UserDetails userDetails) {
        final String username = extractUsername(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
    
    private boolean isTokenExpired(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody()
                .getExpiration()
                .before(new Date());
    }
}

// 3. 用户实体
@Entity
@Table(name = "users")
@Data
public class User implements UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false)
    private String username;
    
    @Column(nullable = false)
    private String password;
    
    @Column(unique = true)
    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<>();
    
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
                .collect(Collectors.toList());
    }
    
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    
    @Override
    public boolean isEnabled() {
        return true;
    }
}

// 4. 角色实体
@Entity
@Table(name = "roles")
@Data
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false)
    private String name;
}

// 5. 用户Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
    Optional<User> findByEmail(String email);
    boolean existsByUsername(String username);
    boolean existsByEmail(String email);
}

// 6. JWT认证过滤器
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Autowired
    private UserRepository userRepository;
    
    @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 token = authHeader.substring(7);
        final String username = jwtTokenUtil.extractUsername(token);
        
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            User user = userRepository.findByUsername(username)
                    .orElseThrow(() -> new RuntimeException("User not found"));
            
            if (jwtTokenUtil.validateToken(token, user)) {
                UsernamePasswordAuthenticationToken authentication = 
                    new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        
        filterChain.doFilter(request, response);
    }
}

// 7. 安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/api/auth/**").permitAll()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        
        return http.build();
    }
}

// 8. 认证控制器
@RestController
@RequestMapping("/api/auth")
public class AuthController {
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        try {
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                    loginRequest.getUsername(),
                    loginRequest.getPassword()
                )
            );
            
            SecurityContextHolder.getContext().setAuthentication(authentication);
            User user = (User) authentication.getPrincipal();
            String token = jwtTokenUtil.generateToken(user);
            
            return ResponseEntity.ok(new JwtResponse(token, user.getUsername()));
        } catch (BadCredentialsException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body("Invalid username or password");
        }
    }
    
    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody RegisterRequest registerRequest) {
        if (userRepository.existsByUsername(registerRequest.getUsername())) {
            return ResponseEntity.badRequest().body("Username already exists");
        }
        
        if (userRepository.existsByEmail(registerRequest.getEmail())) {
            return ResponseEntity.badRequest().body("Email already exists");
        }
        
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
        user.setEmail(registerRequest.getEmail());
        
        // 设置默认角色
        Role userRole = new Role();
        userRole.setName("USER");
        user.getRoles().add(userRole);
        
        userRepository.save(user);
        
        return ResponseEntity.status(HttpStatus.CREATED).body("User registered successfully");
    }
}

// 9. 请求/响应对象
@Data
class LoginRequest {
    private String username;
    private String password;
}

@Data
class RegisterRequest {
    private String username;
    private String password;
    private String email;
}

@Data
class JwtResponse {
    private String token;
    private String username;
    
    public JwtResponse(String token, String username) {
        this.token = token;
        this.username = username;
    }
}

第三部分:高级主题与最佳实践

3.1 Spring事务管理

Spring提供了声明式事务管理,通过@Transactional注解简化事务处理。

示例:复杂的事务场景

@Service
public class OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private PaymentService paymentService;
    
    @Autowired
    private NotificationService notificationService;
    
    // 1. 基本事务管理
    @Transactional
    public Order createOrder(Order order) {
        // 1. 保存订单
        Order savedOrder = orderRepository.save(order);
        
        // 2. 扣减库存
        inventoryService.decreaseStock(order.getProductId(), order.getQuantity());
        
        // 3. 处理支付
        paymentService.processPayment(order);
        
        // 4. 发送通知
        notificationService.sendOrderConfirmation(order);
        
        return savedOrder;
    }
    
    // 2. 事务传播行为
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 使用现有事务,如果没有则创建新事务
        methodB(); // 在同一个事务中执行
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        // 总是创建新事务,挂起当前事务
        // 适合记录日志等独立操作
    }
    
    // 3. 事务隔离级别
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void processConcurrentOrders() {
        // 防止脏读、不可重复读
        // 适合高并发场景
    }
    
    // 4. 事务回滚规则
    @Transactional(
        rollbackFor = {Exception.class},
        noRollbackFor = {IllegalArgumentException.class}
    )
    public void complexTransaction() {
        try {
            // 业务逻辑
        } catch (IllegalArgumentException e) {
            // 不回滚
            throw e;
        } catch (Exception e) {
            // 回滚
            throw e;
        }
    }
    
    // 5. 嵌套事务
    @Transactional(propagation = Propagation.NESTED)
    public void nestedTransaction() {
        // 如果外部事务存在,则创建嵌套事务
        // 如果外部事务回滚,嵌套事务也会回滚
        // 但嵌套事务可以独立回滚
    }
    
    // 6. 只读事务
    @Transactional(readOnly = true)
    public List<Order> getOrdersByUser(Long userId) {
        // 优化性能,避免不必要的锁
        return orderRepository.findByUserId(userId);
    }
    
    // 7. 事务超时
    @Transactional(timeout = 30)
    public void timeSensitiveOperation() {
        // 30秒超时,防止长时间事务
    }
    
    // 8. 手动事务管理
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    public void manualTransaction() {
        TransactionStatus status = transactionManager.getTransaction(
            new DefaultTransactionDefinition()
        );
        
        try {
            // 业务逻辑
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

3.2 异步处理与消息队列

Spring提供了@Async注解和消息队列集成,用于处理异步任务。

示例:异步任务处理

// 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.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

// 2. 异步服务
@Service
public class EmailService {
    
    @Async
    public void sendEmail(String to, String subject, String body) {
        // 模拟发送邮件的耗时操作
        try {
            Thread.sleep(3000); // 模拟3秒延迟
            System.out.println("Email sent to: " + to);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    @Async
    public CompletableFuture<String> sendEmailAsync(String to, String subject, String body) {
        try {
            Thread.sleep(2000);
            return CompletableFuture.completedFuture("Email sent to " + to);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return CompletableFuture.failedFuture(e);
        }
    }
}

// 3. 消息队列集成(RabbitMQ示例)
@Configuration
public class RabbitMQConfig {
    
    @Bean
    public Queue queue() {
        return new Queue("order.queue", true);
    }
    
    @Bean
    public TopicExchange exchange() {
        return new TopicExchange("order.exchange");
    }
    
    @Bean
    public Binding binding(Queue queue, TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("order.*");
    }
}

@Service
public class OrderMessageService {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    public void sendOrderMessage(Order order) {
        rabbitTemplate.convertAndSend("order.exchange", "order.created", order);
    }
    
    @RabbitListener(queues = "order.queue")
    public void processOrderMessage(Order order) {
        System.out.println("Processing order: " + order.getId());
        // 处理订单逻辑
    }
}

3.3 Spring Cloud微服务架构

Spring Cloud提供了构建分布式系统的工具,包括服务发现、配置管理、API网关等。

示例:微服务架构示例

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

// 2. 服务提供者(Product Service)
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductServiceApplication.class, args);
    }
}

@RestController
@RequestMapping("/api/products")
public class ProductController {
    // ... 产品相关接口
}

// 3. 服务消费者(Order Service)
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

// 4. Feign客户端
@FeignClient(name = "product-service")
public interface ProductClient {
    @GetMapping("/api/products/{id}")
    Product getProductById(@PathVariable("id") Long id);
    
    @PostMapping("/api/products")
    Product createProduct(@RequestBody Product product);
}

// 5. API网关(Spring Cloud Gateway)
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

// 6. 配置文件 application.yml
/*
spring:
  cloud:
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/api/products/**
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
*/

// 7. 配置中心(Spring Cloud Config)
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

第四部分:性能优化与调试技巧

4.1 性能优化策略

示例:缓存优化

// 1. 启用缓存
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager() {
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory())
                .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofMinutes(10))
                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())))
                .build();
        return cacheManager;
    }
}

// 2. 使用缓存注解
@Service
public class ProductService {
    
    @Autowired
    private ProductRepository productRepository;
    
    // 缓存结果,key为"product::" + id
    @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 = "#categoryId + '_' + #page + '_' + #size")
    public Page<Product> getProductsByCategory(Long categoryId, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return productRepository.findByCategoryId(categoryId, pageable);
    }
}

4.2 调试与监控

示例:Spring Boot Actuator监控

// 1. 添加依赖
/*
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
*/

// 2. 配置 application.properties
/*
management.endpoints.web.exposure.include=health,info,metrics,loggers
management.endpoint.health.show-details=always
management.endpoint.health.show-details=when_authorized
management.endpoint.health.group.readiness.include=ping,db
management.endpoint.health.group.liveness.include=ping
management.info.env.enabled=true
*/

// 3. 自定义健康检查
@Component
public class CustomHealthIndicator implements HealthIndicator {
    
    @Autowired
    private DataSource dataSource;
    
    @Override
    public Health health() {
        try (Connection connection = dataSource.getConnection()) {
            if (connection.isValid(2)) {
                return Health.up()
                        .withDetail("database", "MySQL")
                        .withDetail("status", "Connected")
                        .build();
            } else {
                return Health.down()
                        .withDetail("database", "MySQL")
                        .withDetail("status", "Connection timeout")
                        .build();
            }
        } catch (Exception e) {
            return Health.down()
                    .withDetail("database", "MySQL")
                    .withDetail("error", e.getMessage())
                    .build();
        }
    }
}

// 4. 自定义指标
@Component
public class CustomMetrics {
    
    private final MeterRegistry meterRegistry;
    private final Counter orderCounter;
    private final Timer orderProcessingTimer;
    
    public CustomMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.orderCounter = Counter.builder("orders.total")
                .description("Total number of orders")
                .register(meterRegistry);
        this.orderProcessingTimer = Timer.builder("orders.processing.time")
                .description("Time taken to process orders")
                .register(meterRegistry);
    }
    
    public void recordOrder() {
        orderCounter.increment();
    }
    
    public void recordOrderProcessingTime(Runnable task) {
        orderProcessingTimer.record(task);
    }
}

第五部分:学习路径与资源推荐

5.1 学习路径建议

  1. 基础阶段(1-2周)

    • 掌握Java基础(集合、多线程、IO)
    • 理解Spring核心概念(IoC、DI、AOP)
    • 学习Spring Boot基础配置
  2. 进阶阶段(2-4周)

    • 深入学习Spring Data JPA
    • 掌握Spring Security
    • 学习REST API设计
  3. 高级阶段(4-6周)

    • 学习Spring事务管理
    • 掌握异步处理与消息队列
    • 理解Spring Cloud微服务架构
  4. 实战阶段(持续)

    • 参与开源项目
    • 构建个人项目
    • 学习性能优化与调试

5.2 推荐学习资源

  1. 官方文档

  2. 书籍推荐

    • 《Spring实战》(Craig Walls著)
    • 《Spring Boot编程思想》(小马哥著)
    • 《Spring Cloud微服务实战》(翟永超著)
  3. 在线课程

  4. 社区与论坛

5.3 实战项目建议

  1. 个人博客系统

    • 技术栈:Spring Boot + Spring Data JPA + Thymeleaf
    • 功能:用户管理、文章发布、评论系统
  2. 电商后台管理系统

    • 技术栈:Spring Boot + Spring Security + Vue.js
    • 功能:商品管理、订单处理、用户管理
  3. 微服务架构项目

    • 技术栈:Spring Cloud + Docker + Kubernetes
    • 功能:服务注册、配置中心、API网关、分布式事务
  4. 实时数据处理系统

    • 技术栈:Spring Boot + Kafka + Redis + Elasticsearch
    • 功能:数据采集、实时分析、可视化展示

结语

Spring框架的学习是一个循序渐进的过程,从理解核心概念到掌握实战技巧,需要持续的学习和实践。本文从零基础开始,详细介绍了Spring的核心概念、Spring Boot的实战开发、高级主题以及性能优化技巧。

关键要点回顾:

  1. IoC和DI是Spring的基石,理解它们是掌握Spring的关键
  2. Spring Boot通过约定优于配置的理念,极大地简化了开发
  3. Spring Data JPA让数据库操作变得简单高效
  4. Spring Security提供了全面的安全解决方案
  5. 事务管理异步处理是企业级应用的核心能力
  6. Spring Cloud为微服务架构提供了完整的解决方案

学习建议:

  • 从简单的REST API开始,逐步增加复杂度
  • 多写代码,多调试,多思考
  • 阅读优秀开源项目的源码
  • 参与社区讨论,解决实际问题

Spring生态系统庞大而强大,掌握它将为你的Java开发之路打开新的大门。祝你学习顺利,早日成为Spring专家!