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的生命周期
- 实例化:创建Bean实例
- 属性赋值:设置Bean的属性值
- 初始化前处理:BeanPostProcessor.postProcessBeforeInitialization()
- 初始化:调用初始化方法
- 初始化后处理:BeanPostProcessor.postProcessAfterInitialization()
- 使用:Bean可以被使用
- 销毁:容器关闭时销毁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);
}
}
请求处理流程
- DispatcherServlet接收请求
- HandlerMapping查找处理器
- HandlerAdapter执行处理器
- ViewResolver解析视图
- 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);
}
}
最佳实践
- 优先使用构造器注入,保证依赖的不可变性
- 合理使用AOP,避免过度使用影响性能
- 正确配置事务边界,避免事务过大或过小
- 使用@Qualifier解决多个Bean的歧义
- 合理使用Bean作用域,避免内存泄漏
- 使用@Profile进行环境隔离
- 利用Spring的事件机制实现解耦
总结
Spring Framework提供了企业级Java开发的完整基础设施,通过IoC容器、AOP、事务管理等核心特性,大大简化了企业级应用的开发。理解Spring的核心概念和工作原理,对于掌握整个Spring生态系统至关重要。