引言:为什么选择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的生命周期包含以下步骤:
- 实例化:通过构造器或工厂方法创建Bean实例
- 属性填充:设置Bean的属性值
- 初始化前:调用BeanNameAware、BeanFactoryAware等Aware接口方法
- 初始化:调用InitializingBean的afterPropertiesSet方法或自定义init方法
- 初始化后:调用BeanPostProcessor的postProcessAfterInitialization方法
- 使用:Bean已就绪,可以被应用使用
- 销毁:调用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容器启动时,它会:
- 扫描指定包下的所有类
- 识别带有@Component、@Service等注解的类
- 解析构造器参数
- 在容器中查找匹配的Bean
- 通过反射调用构造器创建实例
// 模拟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的建议路径:
- 基础阶段:深入理解IoC、DI、AOP等核心概念
- 进阶阶段:掌握Spring Boot、Spring Data JPA、Spring Security
- 高级阶段:学习Spring Cloud、响应式编程、性能调优
- 实战阶段:参与实际项目,积累经验
记住,Spring不仅仅是一个框架,它代表了一种现代化的软件开发理念:约定优于配置、组件化、解耦和可维护性。通过不断学习和实践,你将能够运用Spring构建出高质量的企业级应用。
