【Java高级篇】——第14篇:深入详解Spring框架基础

第14篇:深入详解Spring框架基础

Spring框架是Java企业级应用开发的事实标准,其核心思想是 控制反转(IoC)面向切面编程(AOP)。本文将从Spring容器、Bean管理、依赖注入、AOP实现出发,结合配置方式演进与核心源码解析,系统剖析Spring框架的基础架构与核心机制。


1. Spring生态全景

模块核心功能典型应用场景
Spring CoreIoC容器、Bean管理、资源加载所有Spring应用的基础
Spring AOP切面编程、动态代理日志、事务等横切关注点
Spring MVCWeb层框架,支持RESTful开发Web应用开发
Spring Data统一数据访问抽象(JPA、MongoDB、Redis)数据库操作
Spring Security认证与授权框架系统安全管控
Spring Boot自动化配置、快速启动微服务开发

2. IoC容器与Bean管理

2.1 容器核心接口
  • BeanFactory:基础容器接口,提供Bean的注册与获取(延迟初始化)
  • ApplicationContext:扩展自BeanFactory,增加事件发布、国际化等企业级功能(立即初始化)
// 示例:ClassPathXmlApplicationContext使用
ApplicationContext context = 
    new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean(UserService.class);
2.2 Bean作用域
作用域类型说明
singleton默认作用域,容器中唯一实例
prototype每次请求创建新实例
requestWeb应用中每个HTTP请求一个实例
sessionWeb应用中每个用户会话一个实例
applicationWeb应用中ServletContext生命周期内唯一实例

配置示例:

<bean id="user" class="com.example.User" scope="prototype"/>
2.3 Bean生命周期
  1. 实例化(Instantiation)
  2. 属性填充(Population)
  3. BeanNameAware接口回调
  4. BeanFactoryAware接口回调
  5. 前置初始化(BeanPostProcessor.postProcessBeforeInitialization)
  6. 初始化方法(@PostConstruct、InitializingBean)
  7. 后置初始化(BeanPostProcessor.postProcessAfterInitialization)
  8. 销毁(@PreDestroy、DisposableBean)

3. 依赖注入(DI)实现方式

3.1 注入类型对比
方式优点缺点
构造器注入保证依赖不可变,避免NPE参数较多时代码冗长
Setter注入灵活性高,适合可选依赖可能产生部分初始化的对象
字段注入代码简洁破坏封装性,测试困难

注解示例:

@Component
public class OrderService {
    // 构造器注入(推荐)
    private final UserService userService;
    public OrderService(UserService userService) {
        this.userService = userService;
    }

    // Setter注入
    private PaymentService paymentService;
    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}
3.2 自动装配模式
模式说明
byType根据类型自动装配(需确保类型唯一)
byName根据Bean名称匹配属性名
constructor类似byType,但应用于构造器参数
@Qualifier指定具体Bean名称解决歧义

4. AOP实现原理

4.1 核心概念
  • 切面(Aspect):横切关注点的模块化(如日志、事务)
  • 连接点(Joinpoint):程序执行点(方法执行、异常处理)
  • 通知(Advice):切面在连接点的动作(前置、后置、环绕等)
  • 切点(Pointcut):匹配连接点的表达式
4.2 JDK动态代理 vs CGLIB代理
特性JDK动态代理CGLIB代理
代理对象要求必须实现接口可代理普通类
性能生成快,调用慢生成慢,调用快
方法拦截通过InvocationHandler接口通过方法拦截器MethodInterceptor

配置强制使用CGLIB:

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {}
4.3 AOP实战:日志切面
@Aspect
@Component
public class LogAspect {
    // 定义切点:所有Service层方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}
    
    // 前置通知
    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Method " + methodName + " starts");
    }
    
    // 环绕通知
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = pjp.proceed();
        long duration = System.currentTimeMillis() - start;
        System.out.println("Method executed in " + duration + "ms");
        return result;
    }
}

5. 配置方式演进

5.1 XML配置(传统方式)
<!-- Bean定义 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
    <property name="jdbcUrl" value="${db.url}"/>
    <property name="username" value="${db.user}"/>
</bean>

<!-- AOP配置 -->
<aop:config>
    <aop:aspect ref="logAspect">
        <aop:pointcut id="serviceMethods" 
            expression="execution(* com.example.service.*.*(..))"/>
        <aop:before method="logBefore" pointcut-ref="serviceMethods"/>
    </aop:aspect>
</aop:config>
5.2 Java Config(现代方式)
@Configuration
@PropertySource("classpath:app.properties")
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {
    @Bean
    public DataSource dataSource(
        @Value("${db.url}") String url,
        @Value("${db.user}") String user) {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl(url);
        ds.setUsername(user);
        return ds;
    }
}
5.3 注解驱动(主流方式)
@Service
public class UserService {
    @Autowired
    private UserRepository userRepo;
    
    @Transactional
    public User createUser(User user) {
        return userRepo.save(user);
    }
}

6. Spring核心源码解析

6.1 Bean创建流程
  1. BeanDefinition加载:解析配置生成Bean定义
  2. 实例化:通过反射或工厂方法创建对象
  3. 属性填充:注入依赖的Bean
  4. 初始化:调用初始化方法和BeanPostProcessor
  5. 注册销毁方法:记录@PreDestroy方法
6. 循环依赖解决
  • 三级缓存机制
    1. singletonFactories(三级缓存,存放ObjectFactory)
    2. earlySingletonObjects(二级缓存,存放早期对象)
    3. singletonObjects(一级缓存,存放完整Bean)

处理流程

  1. A创建时将自己提前暴露到三级缓存
  2. A填充属性时发现依赖B,触发B的创建
  3. B填充属性时从三级缓存获取A的ObjectFactory
  4. B完成初始化后,A继续完成属性填充和初始化

7. 常见问题与解决方案

7.1 Bean注入失败排查
  1. 检查@ComponentScan包路径是否正确
  2. 确认Bean是否被正确标记(@Service/@Component)
  3. 使用context.getBeanDefinitionNames()查看所有注册Bean
  4. 检查是否存在多个同类型Bean导致歧义(使用@Qualifier解决)
7.2 事务失效场景
  • 原因
    • 非public方法使用@Transactional
    • 同一类内方法调用(未经过代理)
    • 异常类型未被捕获(默认只回滚RuntimeException)
  • 解决
    • 通过AopContext.currentProxy()获取代理对象
    • 配置rollbackFor属性

8. 最佳实践与进阶建议

  1. 配置规范

    • 生产环境使用Java Config或注解驱动
    • 敏感信息(如密码)使用加密或外部化配置
  2. 性能优化

    • 合理设置Bean作用域(避免无意义的prototype)
    • 延迟初始化非关键Bean(@Lazy)
  3. 学习路径

    • 掌握Spring官方文档核心章节
    • 调试Spring源码(从BeanFactory入手)
    • 实践Spring Boot自动配置原理

附:Spring核心注解速查表

注解作用等效XML配置
@Component通用组件声明<bean class="..."/>
@Autowired自动装配依赖<property name ref="..."/>
@Configuration标记配置类<beans>...</beans>
@Bean声明Bean定义<bean id="...">
@Profile环境特定配置激活<beans profile="...">
@Enable*模块功能开关(如@EnableCaching)<cache:annotation-driven/>

通过深入理解Spring框架的核心机制,开发者能够构建松耦合、易维护的企业级应用,并为掌握Spring Boot、Spring Cloud等进阶技术奠定坚实基础。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿享天开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值