Spring Framework

Spring Framework

概述

Spring Framework是Java平台上的开源应用框架,为企业级Java开发提供了全面的基础设施支持。它的核心特性包括依赖注入(DI)、面向切面编程(AOP)、事务管理等。

核心概念

IoC容器(控制反转)

IoC(Inversion of Control)是Spring的核心概念,通过容器来管理对象的创建和依赖关系。

依赖注入方式

构造器注入

java
@Component
public class UserService {
    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
@Component
public class UserService {
    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

Setter注入

java
@Component
public class UserService {
    private UserRepository userRepository;
    
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
@Component
public class UserService {
    private UserRepository userRepository;
    
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

字段注入

java
@Component
public class UserService {
    @Autowired
    private UserRepository userRepository;
}
@Component
public class UserService {
    @Autowired
    private UserRepository userRepository;
}

Bean的生命周期

  1. 实例化:创建Bean实例
  2. 属性赋值:设置Bean的属性值
  3. 初始化前处理:BeanPostProcessor.postProcessBeforeInitialization()
  4. 初始化:调用初始化方法
  5. 初始化后处理:BeanPostProcessor.postProcessAfterInitialization()
  6. 使用:Bean可以被使用
  7. 销毁:容器关闭时销毁Bean
java
@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
    
    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct");
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet()");
    }
    
    @PreDestroy
    public void cleanup() {
        System.out.println("@PreDestroy");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean.destroy()");
    }
}
@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
    
    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct");
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet()");
    }
    
    @PreDestroy
    public void cleanup() {
        System.out.println("@PreDestroy");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean.destroy()");
    }
}

Bean作用域

java
@Component
@Scope("singleton")    // 单例(默认)
public class SingletonBean {}

@Component
@Scope("prototype")    // 原型,每次获取创建新实例
public class PrototypeBean {}

@Component
@Scope("request")      // Web环境:每个HTTP请求
public class RequestBean {}

@Component
@Scope("session")      // Web环境:每个HTTP会话
public class SessionBean {}
@Component
@Scope("singleton")    // 单例(默认)
public class SingletonBean {}

@Component
@Scope("prototype")    // 原型,每次获取创建新实例
public class PrototypeBean {}

@Component
@Scope("request")      // Web环境:每个HTTP请求
public class RequestBean {}

@Component
@Scope("session")      // Web环境:每个HTTP会话
public class SessionBean {}

AOP(面向切面编程)

核心概念

  • 切面(Aspect):横切关注点的模块化
  • 连接点(Join Point):程序执行的某个特定位置
  • 切点(Pointcut):连接点的集合
  • 通知(Advice):在切点执行的代码
  • 织入(Weaving):将切面应用到目标对象的过程

通知类型

java
@Aspect
@Component
public class LoggingAspect {
    
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}
    
    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before: " + joinPoint.getSignature().getName());
    }
    
    @After("serviceLayer()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After: " + joinPoint.getSignature().getName());
    }
    
    @AfterReturning(pointcut = "serviceLayer()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("AfterReturning: " + result);
    }
    
    @AfterThrowing(pointcut = "serviceLayer()", throwing = "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
        System.out.println("AfterThrowing: " + error.getMessage());
    }
    
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            Object result = joinPoint.proceed();
            long elapsedTime = System.currentTimeMillis() - start;
            System.out.println("Method execution time: " + elapsedTime + "ms");
            return result;
        } catch (IllegalArgumentException e) {
            System.out.println("Illegal argument: " + Arrays.toString(joinPoint.getArgs()));
            throw e;
        }
    }
}
@Aspect
@Component
public class LoggingAspect {
    
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}
    
    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before: " + joinPoint.getSignature().getName());
    }
    
    @After("serviceLayer()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After: " + joinPoint.getSignature().getName());
    }
    
    @AfterReturning(pointcut = "serviceLayer()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("AfterReturning: " + result);
    }
    
    @AfterThrowing(pointcut = "serviceLayer()", throwing = "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
        System.out.println("AfterThrowing: " + error.getMessage());
    }
    
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            Object result = joinPoint.proceed();
            long elapsedTime = System.currentTimeMillis() - start;
            System.out.println("Method execution time: " + elapsedTime + "ms");
            return result;
        } catch (IllegalArgumentException e) {
            System.out.println("Illegal argument: " + Arrays.toString(joinPoint.getArgs()));
            throw e;
        }
    }
}

事务管理

声明式事务

java
@Service
@Transactional
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Transactional(readOnly = true)
    public User findById(Long id) {
        return userRepository.findById(id);
    }
    
    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,
        rollbackFor = Exception.class
    )
    public void saveUser(User user) {
        userRepository.save(user);
    }
}
@Service
@Transactional
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Transactional(readOnly = true)
    public User findById(Long id) {
        return userRepository.findById(id);
    }
    
    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,
        rollbackFor = Exception.class
    )
    public void saveUser(User user) {
        userRepository.save(user);
    }
}

事务传播行为

  • REQUIRED:如果当前存在事务,则加入该事务;如果不存在,则创建新事务
  • REQUIRES_NEW:创建新事务,如果当前存在事务,则挂起当前事务
  • SUPPORTS:如果当前存在事务,则加入该事务;如果不存在,则以非事务方式执行
  • NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则挂起当前事务
  • MANDATORY:如果当前存在事务,则加入该事务;如果不存在,则抛出异常
  • NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
  • NESTED:如果当前存在事务,则在嵌套事务内执行

Spring MVC

核心组件

java
@Controller
@RequestMapping("/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/{id}")
    @ResponseBody
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
    
    @PostMapping
    @ResponseBody
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }
    
    @PutMapping("/{id}")
    @ResponseBody
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userService.update(user);
    }
    
    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.delete(id);
    }
}
@Controller
@RequestMapping("/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/{id}")
    @ResponseBody
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
    
    @PostMapping
    @ResponseBody
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }
    
    @PutMapping("/{id}")
    @ResponseBody
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userService.update(user);
    }
    
    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.delete(id);
    }
}

请求处理流程

  1. DispatcherServlet接收请求
  2. HandlerMapping查找处理器
  3. HandlerAdapter执行处理器
  4. ViewResolver解析视图
  5. View渲染响应

异常处理

java
@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(UserNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorResponse handleUserNotFound(UserNotFoundException ex) {
        return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
    }
    
    @ExceptionHandler(ValidationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorResponse handleValidation(ValidationException ex) {
        return new ErrorResponse("VALIDATION_ERROR", ex.getMessage());
    }
}
@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(UserNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorResponse handleUserNotFound(UserNotFoundException ex) {
        return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
    }
    
    @ExceptionHandler(ValidationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorResponse handleValidation(ValidationException ex) {
        return new ErrorResponse("VALIDATION_ERROR", ex.getMessage());
    }
}

数据访问

JDBC Template

java
@Repository
public class UserRepositoryImpl implements UserRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public User findById(Long id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new UserRowMapper(), id);
    }
    
    @Override
    public void save(User user) {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        jdbcTemplate.update(sql, user.getName(), user.getEmail());
    }
    
    private static class UserRowMapper implements RowMapper<User> {
        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User user = new User();
            user.setId(rs.getLong("id"));
            user.setName(rs.getString("name"));
            user.setEmail(rs.getString("email"));
            return user;
        }
    }
}
@Repository
public class UserRepositoryImpl implements UserRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public User findById(Long id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new UserRowMapper(), id);
    }
    
    @Override
    public void save(User user) {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        jdbcTemplate.update(sql, user.getName(), user.getEmail());
    }
    
    private static class UserRowMapper implements RowMapper<User> {
        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User user = new User();
            user.setId(rs.getLong("id"));
            user.setName(rs.getString("name"));
            user.setEmail(rs.getString("email"));
            return user;
        }
    }
}

配置方式

Java配置

java
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example")
public class WebConfig implements WebMvcConfigurer {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        dataSource.setUsername("user");
        dataSource.setPassword("password");
        return dataSource;
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
    
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example")
public class WebConfig implements WebMvcConfigurer {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        dataSource.setUsername("user");
        dataSource.setPassword("password");
        return dataSource;
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
    
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }
}

注解配置

java
@Configuration
@EnableTransactionManagement
@EnableAspectJAutoProxy
public class AppConfig {
    
    @Bean
    @Primary
    public UserService primaryUserService() {
        return new UserServiceImpl();
    }
    
    @Bean
    @Qualifier("backup")
    public UserService backupUserService() {
        return new BackupUserServiceImpl();
    }
}
@Configuration
@EnableTransactionManagement
@EnableAspectJAutoProxy
public class AppConfig {
    
    @Bean
    @Primary
    public UserService primaryUserService() {
        return new UserServiceImpl();
    }
    
    @Bean
    @Qualifier("backup")
    public UserService backupUserService() {
        return new BackupUserServiceImpl();
    }
}

Spring Boot集成

Spring Framework是Spring Boot的基础,Spring Boot通过自动配置简化了Spring应用的开发:

java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

最佳实践

  1. 优先使用构造器注入,保证依赖的不可变性
  2. 合理使用AOP,避免过度使用影响性能
  3. 正确配置事务边界,避免事务过大或过小
  4. 使用@Qualifier解决多个Bean的歧义
  5. 合理使用Bean作用域,避免内存泄漏
  6. 使用@Profile进行环境隔离
  7. 利用Spring的事件机制实现解耦

总结

Spring Framework提供了企业级Java开发的完整基础设施,通过IoC容器、AOP、事务管理等核心特性,大大简化了企业级应用的开发。理解Spring的核心概念和工作原理,对于掌握整个Spring生态系统至关重要。