返回 元婴・Spring 道韵观想
01Spring核心:从IOC容器到AOP切面的深度解析
博主
大约 8 分钟
Spring核心:从IOC容器到AOP切面的深度解析
Spring不仅仅是一个框架,更是一种编程思想
开篇:为什么Spring如此重要?
在Java生态系统中,Spring框架已经成为事实上的标准。它不仅简化了企业级应用开发,更重要的是,它引入了一系列优秀的设计理念和编程模式,如依赖注入、面向切面编程等。
IOC容器:从"new"到"依赖注入"的思维转变
IOC(Inversion of Control,控制反转)是Spring的核心概念之一。它将对象的创建和依赖管理从代码中分离出来,交由容器统一管理。
传统方式:主动创建对象
// 传统方式:硬编码依赖
public class UserService {
private UserDao userDao = new UserDaoImpl(); // 硬编码依赖
public void saveUser(User user) {
userDao.save(user);
}
}
Spring方式:依赖注入
// Spring方式:依赖注入
public class UserService {
private UserDao userDao; // 只声明依赖
// 构造器注入
public UserService(UserDao userDao) {
this.userDao = userDao;
}
// 或者 setter 注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void saveUser(User user) {
userDao.save(user);
}
}
配置方式
XML配置:
<!-- 配置Bean -->
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>
<bean id="userService" class="com.example.service.UserService">
<!-- 构造器注入 -->
<constructor-arg ref="userDao"/>
<!-- 或者 setter 注入 -->
<!-- <property name="userDao" ref="userDao"/> -->
</bean>
注解配置:
// 组件扫描
@Component
public class UserDaoImpl implements UserDao {
// 实现方法
}
@Service
public class UserService {
@Autowired // 自动注入
private UserDao userDao;
// 业务方法
}
// 启用组件扫描
@Configuration
@ComponentScan("com.example")
public class AppConfig {
// 配置类
}
Java配置:
@Configuration
public class AppConfig {
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
@Bean
public UserService userService() {
return new UserService(userDao());
}
}
AOP切面:从"散落在各处的代码"到"集中管理"的优雅解决方案
AOP(Aspect-Oriented Programming,面向切面编程)是Spring的另一个核心概念。它允许你将横切关注点(如日志、事务、安全等)从业务逻辑中分离出来,集中管理。
AOP核心概念
- 切面(Aspect):横切关注点的模块化
- 连接点(Join Point):程序执行过程中的点
- 通知(Advice):在连接点执行的代码
- 切点(Pointcut):匹配连接点的表达式
- 引入(Introduction):向现有类添加方法或字段
- 织入(Weaving):将切面与目标对象结合
示例:日志切面
// 定义切面
@Aspect
@Component
public class LoggingAspect {
// 定义切点
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
// 前置通知
@Before("serviceMethods()")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("调用方法:" + joinPoint.getSignature().getName());
System.out.println("参数:" + Arrays.toString(joinPoint.getArgs()));
}
// 后置通知
@AfterReturning(
pointcut = "serviceMethods()",
returning = "result"
)
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
System.out.println("方法返回值:" + result);
}
// 异常通知
@AfterThrowing(
pointcut = "serviceMethods()",
throwing = "exception"
)
public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {
System.out.println("方法抛出异常:" + exception.getMessage());
}
// 环绕通知
@Around("serviceMethods()")
public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
try {
// 执行目标方法
Object result = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println("方法执行时间:" + (endTime - startTime) + "ms");
return result;
} catch (Throwable throwable) {
System.out.println("方法执行异常:" + throwable.getMessage());
throw throwable;
}
}
}
Spring Bean:生命周期与作用域
Bean生命周期
- 实例化:创建Bean实例
- 属性赋值:设置Bean的属性
- 初始化前:执行BeanPostProcessor的postProcessBeforeInitialization方法
- 初始化:执行InitializingBean的afterPropertiesSet方法或自定义初始化方法
- 初始化后:执行BeanPostProcessor的postProcessAfterInitialization方法
- 使用:Bean可以被应用程序使用
- 销毁:执行DisposableBean的destroy方法或自定义销毁方法
Bean作用域
- singleton:单例,默认作用域
- prototype:原型,每次获取都创建新实例
- request:请求,每个HTTP请求创建一个实例
- session:会话,每个HTTP会话创建一个实例
- application:应用,每个ServletContext创建一个实例
- websocket:WebSocket,每个WebSocket会话创建一个实例
事务管理:从"手动控制"到"声明式事务"的飞跃
Spring提供了强大的事务管理能力,支持编程式事务和声明式事务。
声明式事务
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional // 声明式事务
public void transferMoney(Long fromUserId, Long toUserId, BigDecimal amount) {
// 扣款
userDao.decreaseBalance(fromUserId, amount);
// 这里如果发生异常,事务会自动回滚
// int i = 1 / 0;
// 存款
userDao.increaseBalance(toUserId, amount);
}
}
事务属性
@Transactional(
propagation = Propagation.REQUIRED, // 传播行为
isolation = Isolation.DEFAULT, // 隔离级别
timeout = 30, // 超时时间
readOnly = false, // 是否只读
rollbackFor = Exception.class, // 回滚异常
noRollbackFor = RuntimeException.class // 不回滚异常
)
public void transferMoney(Long fromUserId, Long toUserId, BigDecimal amount) {
// 业务逻辑
}
条件注解:根据环境动态配置
Spring 4.0引入了条件注解,允许根据特定条件决定是否创建Bean。
@Configuration
public class DatabaseConfig {
@Bean
@Conditional(DevCondition.class) // 开发环境条件
public DataSource devDataSource() {
// 开发环境数据源
return createDataSource("dev");
}
@Bean
@Conditional(ProdCondition.class) // 生产环境条件
public DataSource prodDataSource() {
// 生产环境数据源
return createDataSource("prod");
}
private DataSource createDataSource(String environment) {
// 创建数据源
return dataSource;
}
}
// 开发环境条件
public class DevCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return "dev".equals(context.getEnvironment().getProperty("spring.profiles.active"));
}
}
// 生产环境条件
public class ProdCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return "prod".equals(context.getEnvironment().getProperty("spring.profiles.active"));
}
}
事件机制:松耦合的组件通信
Spring提供了事件机制,允许组件之间通过事件进行松耦合通信。
// 自定义事件
public class UserRegisteredEvent extends ApplicationEvent {
private 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;
public void registerUser(User user) {
// 注册用户
// ...
// 发布事件
eventPublisher.publishEvent(new UserRegisteredEvent(this, user));
}
}
// 事件监听器
@Component
public class UserEventListener {
@EventListener
public void handleUserRegisteredEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 处理用户注册事件,如发送邮件、短信等
System.out.println("用户注册成功:" + user.getUsername());
}
}
实战建议
- 优先使用注解配置:注解配置更简洁,易于维护
- 合理使用作用域:根据实际需求选择合适的Bean作用域
- 善用AOP:将横切关注点(如日志、事务、安全)分离出来
- 理解生命周期:了解Bean生命周期有助于编写更健壮的代码
- 合理配置事务:根据业务需求配置合适的事务属性
- 使用条件配置:根据环境动态调整配置
- 利用事件机制:实现松耦合的组件通信
结语
Spring框架的核心价值在于它引入的设计理念和编程模式,而不仅仅是它的功能。通过理解IOC、AOP等核心概念,你可以编写出更加模块化、可测试、可维护的代码。
Spring的生态系统非常庞大,除了核心框架外,还包括Spring Boot、Spring Cloud、Spring Security等一系列优秀的项目。掌握Spring核心概念,是学习整个Spring生态的基础。
在实际开发中,要根据具体需求选择合适的Spring特性,避免过度设计。记住,技术是为业务服务的,选择合适的工具和方法,才能事半功倍。
知识点测试
读完文章了?来测试一下你对知识点的掌握程度吧!
评论区
使用 GitHub 账号登录后即可发表评论,支持 Markdown 格式。
如果评论系统无法加载,请确保:
- 您的网络可以访问 GitHub
- giscus GitHub App 已安装到仓库
- 仓库已启用 Discussions 功能