Spring源码深度解析:把框架核心讲透,让面试官刮目相看

0 阅读11分钟

Spring源码深度解析:把框架核心讲透,让面试官刮目相看

前言

🎯 写在前面:Spring是Java后端开发的"利刃",几乎所有Java程序员每天都在用。但你真的了解Spring的底层原理吗?

在Java后端面试中,Spring永远是逃不开的话题。而Spring的核心就是IOC容器AOP切面编程

很多小伙伴都遇到过这些问题:

"Spring是怎么把Bean创建出来的?" "依赖注入是怎么实现的?" "AOP的代理是怎么生成的?JDK动态代理和CGLIB有什么区别?" "Bean的生命周期到底有哪些步骤?" "循环依赖是怎么解决的?"

今天这篇文章,我将从源码层面深入剖析Spring IOC/AOP的原理,用图文并茂的方式把这些"八股文"讲透,让你面试再也不慌!


![Spring IOC/AOP源码解析封面]


一、Spring到底是个什么东西?

1.1 重新认识Spring

在正式讲解源码之前,我们先来理解Spring到底是什么。

┌─────────────────────────────────────────────────────────────────────┐
│                         Spring框架架构                               │
│                                                                      │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │                      Spring Framework                      │   │
│   │                                                              │   │
│   │   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │   │
│   │   │     IOC     │  │     AOP     │  │    事务     │        │   │
│   │   │  控制反转   │  │  面向切面   │  │   管理      │        │   │
│   │   └─────────────┘  └─────────────┘  └─────────────┘        │   │
│   │          │               │               │                  │   │
│   │          └───────────────┴───────────────┘                  │   │
│   │                          │                                  │   │
│   │         ┌────────────────┼────────────────┐                │   │
│   │         │                │                │                │   │
│   │   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │   │
│   │   │   JDBC     │  │   Web MVC   │  │   测试      │        │   │
│   │   │   模板     │  │             │  │             │        │   │
│   │   └─────────────┘  └─────────────┘  └─────────────┘        │   │
│   │                                                              │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
│                        Spring Boot                                  │
│                        Spring Cloud                                 │
│                        Spring Data                                  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

1.2 IOC到底是什么?

IOC = Inversion of Control = 控制反转

这是Spring的核心思想。听起来高大上,其实很简单:

传统写法(主动):

public class UserService {
    
    // 主动创建依赖
    private UserDao userDao = new UserDaoImpl();
    
    public void save(User user) {
        // 自己管理依赖
        userDao.save(user);
    }
}

IOC写法(被动):

public class UserService {
    
    // 被动接收依赖,由Spring注入
    private UserDao userDao;
    
    // Spring通过构造方法或setter注入
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
    
    public void save(User user) {
        // 不用关心userDao怎么来的
        userDao.save(user);
    }
}

IOC的好处:

┌─────────────────────────────────────────────────────────────────────┐
│                         IOC的优势                                   │
│                                                                      │
│   传统方式:                        IOC方式:                        │
│   ┌─────────────────┐              ┌─────────────────┐             │
│   │  UserService   │              │  UserService   │             │
│   │    直接依赖    │              │    间接依赖    │             │
│   │   UserDaoImpl  │              │  Spring容器    │             │
│   └─────────────────┘              └────────┬────────┘             │
│         │                                    │                      │
│         │  耦合度高,                      │  耦合度低              │
│         │  难以测试                       │  易于测试             │
│         │  难以替换                       │  易于替换             │
│         │  难以扩展                       │  易于扩展             │
│         ▼                                    ▼                      │
│   ┌─────────────────┐              ┌─────────────────┐             │
│   │  强依赖实现类   │              │  依赖接口/容器   │             │
│   └─────────────────┘              └─────────────────┘             │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

1.3 AOP又是什么?

AOP = Aspect Oriented Programming = 面向切面编程

AOP的思想是:在不修改原有代码的情况下,增强功能

传统方式(侵入性):

public class UserService {
    
    public void save(User user) {
        // ❌ 重复代码:日志记录
        log.info("开始保存用户: " + user.getName());
        
        long startTime = System.currentTimeMillis();  // ❌ 重复代码:计时
        
        try {
            // 核心业务逻辑
            doSave(user);
            
            // ❌ 重复代码:日志记录
            log.info("保存用户成功: " + user.getName());
        } catch (Exception e) {
            // ❌ 重复代码:日志记录
            log.error("保存用户失败: " + user.getName(), e);
            throw e;
        }
        
        // ❌ 重复代码:计时
        long endTime = System.currentTimeMillis();
        log.info("保存用户耗时: " + (endTime - startTime) + "ms");
    }
    
    public void update(User user) {
        // 又要复制一遍上述代码... ❌
    }
    
    public void delete(Long id) {
        // 又要复制一遍上述代码... ❌
    }
}

AOP方式(非侵入):

// 切面类:定义增强逻辑
@Aspect
@Component
public class LoggingAspect {
    
    @Around("execution(* com.example.service.UserService.*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 增强逻辑只写一次
        log.info("开始执行: " + point.getSignature());
        
        long startTime = System.currentTimeMillis();
        
        Object result = point.proceed();
        
        long endTime = System.currentTimeMillis();
        log.info("执行完成,耗时: " + (endTime - startTime) + "ms");
        
        return result;
    }
}

// 业务类:保持纯净
@Service
public class UserService {
    
    public void save(User user) {
        // 只需要写核心业务逻辑
        doSave(user);
    }
    
    public void update(User user) {
        doUpdate(user);
    }
    
    public void delete(Long id) {
        doDelete(id);
    }
}

二、IOC容器启动流程:源码深度解析

2.1 整体架构图

┌─────────────────────────────────────────────────────────────────────┐
│                     Spring IOC容器架构                               │
│                                                                      │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │                    ApplicationContext                       │   │
│   │                    (应用上下文)                              │   │
│   └──────────────────────────┬────────────────────────────────┘   │
│                              │                                      │
│   ┌──────────────────────────▼────────────────────────────────┐   │
│   │                     DefaultListableBeanFactory              │   │
│   │                    (核心工厂类)                              │   │
│   │                                                              │   │
│   │   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │   │
│   │   │  BeanDefinition │ │  SingletonRegistry│ │  BeanPostProcessor│   │
│   │   │   注册表     │  │  单例缓存    │  │  后置处理器 │        │   │
│   │   └─────────────┘  └─────────────┘  └─────────────┘        │   │
│   │                                                              │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

2.2 启动入口:refresh()方法

Spring容器的启动,核心在于AbstractApplicationContext.refresh()方法:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {
    
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 1️⃣ 准备工作:设置启动时间、状态
            prepareRefresh();
            
            // 2️⃣ 获取BeanFactory(创建或获取容器)
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            
            // 3️⃣ 准备BeanFactory(设置类加载器、表达式解析器等)
            prepareBeanFactory(beanFactory);
            
            try {
                // 4️⃣ 允许BeanFactory后置处理(子类可以覆盖)
                postProcessBeanFactory(beanFactory);
                
                // 5️⃣ 执行BeanFactory后置处理器
                invokeBeanFactoryPostProcessors(beanFactory);
                
                // 6️⃣ 注册Bean后置处理器
                registerBeanPostProcessors(beanFactory);
                
                // 7️⃣ 初始化消息源
                initMessageSource();
                
                // 8️⃣ 初始化事件广播器
                initApplicationEventMulticaster();
                
                // 9️⃣ 子类初始化(模板方法)
                onRefresh();
                
                // 🔟 注册监听器
                registerListeners();
                
                // 1️⃣1️⃣ 实例化所有单例Bean
                finishBeanFactoryInitialization(beanFactory);
                
                // 1️⃣2️⃣ 完成刷新:发布事件
                finishRefresh();
            } catch (BeansException ex) {
                destroyBeans();
                cancelRefresh(ex);
                throw ex;
            }
        }
    }
}

流程图:

┌─────────────────────────────────────────────────────────────────────┐
│                         refresh() 流程图                            │
│                                                                      │
│   prepareRefresh()                                                  │
│         │                                                           │
│         ▼                                                           │
│   obtainFreshBeanFactory()                                          │
│         │                                                           │
│         ▼                                                           │
│   prepareBeanFactory()                                              │
│         │                                                           │
│         ▼                                                           │
│   postProcessBeanFactory()                                          │
│         │                                                           │
│         ▼                                                           │
│   invokeBeanFactoryPostProcessors()  ◄── BeanDefinitionRegistryPostProcessor│
│         │                                                           │
│         ▼                                                           │
│   registerBeanPostProcessors()  ◄── BeanPostProcessor              │
│         │                                                           │
│         ▼                                                           │
│   initMessageSource()                                               │
│         │                                                           │
│         ▼                                                           │
│   initApplicationEventMulticaster()                                │
│         │                                                           │
│         ▼                                                           │
│   onRefresh()  ◄── 子类扩展点                                       │
│         │                                                           │
│         ▼                                                           │
│   registerListeners()                                               │
│         │                                                           │
│         ▼                                                           │
│   finishBeanFactoryInitialization()  ◄── 实例化所有单例Bean       │
│         │                                                           │
│         ▼                                                           │
│   finishRefresh()  ◄── 发布ContextRefreshedEvent                   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

2.3 BeanDefinition加载:资源定位

第一步:obtainFreshBeanFactory()

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 刷新BeanFactory
    refreshBeanFactory();
    // 返回BeanFactory
    return getBeanFactory();
}

BeanDefinition从哪里来?

// Spring Boot会自动扫描
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// 等价于XML配置
<context:component-scan base-package="com.example"/>

ComponentScan扫描过程:

┌─────────────────────────────────────────────────────────────────────┐
│                         Bean扫描流程                                │
│                                                                      │
│   1️⃣ 指定扫描包                                                     │
│       @ComponentScan("com.example.service")                        │
│                    │                                                │
│                    ▼                                                │
│   2️⃣ 扫描class文件                                                  │
│       ┌─────────┐  ┌─────────┐  ┌─────────┐                        │
│       │UserDao  │  │UserSvc  │  │UserCtrl │                        │
│       │.class   │  │.class   │  │.class   │                        │
│       └─────────┘  └─────────┘  └─────────┘                        │
│                    │                                                │
│                    ▼                                                │
│   3️⃣ 解析注解                                                       │
│       @Component → BeanDefinition                                  │
│       @Service   → BeanDefinition                                  │
│       @Repository→BeanDefinition                                    │
│                    │                                                │
│                    ▼                                                │
│   4️⃣ 注册到BeanDefinitionRegistry                                  │
│       ┌──────────────────────────────────────────┐                 │
│       │         BeanDefinitionMap                 │                 │
│       │  "userDao"   → BeanDefinition            │                 │
│       │  "userService" → BeanDefinition          │                 │
│       │  "userController" → BeanDefinition       │                 │
│       └──────────────────────────────────────────┘                 │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

2.4 BeanDefinition结构解析

/**
 * BeanDefinition - Bean的定义信息
 * 
 * 类似于Class和Object的关系:
 * Class是对类的描述
 * BeanDefinition是对Bean的描述
 */
public class BeanDefinitionDemo {
    
    public static void main(String[] args) {
        // 假设有这样的类
        // @Component
        // public class UserService {
        //     @Autowired
        //     private UserDao userDao;
        //     
        //     @Value("${app.name}")
        //     private String appName;
        // }
        
        // 生成的BeanDefinition包含:
        BeanDefinition bd = new RootBeanDefinition(UserService.class);
        
        // 1. beanClassName:Bean的全限定类名
        bd.setBeanClassName("com.example.service.UserService");
        
        // 2. scope:作用域
        bd.setScope(BeanDefinition.SCOPE_SINGLETON);  // 单例
        
        // 3. lazyInit:是否懒加载
        bd.setLazyInit(false);  // 默认false,立即加载
        
        // 4. autowireMode:自动装配模式
        bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        
        // 5. propertyValues:属性值(@Value注入的值)
        MutablePropertyValues pvs = new MutablePropertyValues();
        pvs.add("appName", "my-app");
        bd.setPropertyValues(pvs);
        
        // 6. constructorArgumentValues:构造方法参数(@Autowired注入的值)
        ConstructorArgumentValues cav = new ConstructorArgumentValues();
        // 假设UserService有构造方法参数
        bd.setConstructorArgumentValues(cav);
    }
}

2.5 Bean实例化:createBean()

这是IOC容器最核心的方法——Bean是如何被创建出来的?

/**
 * AbstractAutowireCapableBeanFactory.createBean()
 * 
 * Bean实例化核心流程
 */
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    
    // 1️⃣ 解析beanClass(可能是一个Class,也可能是一个字符串)
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    
    try {
        // 2️⃣ 合并父子BeanDefinition
        mbd = getMergedLocalBeanDefinition(beanName);
        
        // 3️⃣ 检查抽象标记(抽象Bean不能实例化)
        if (mbd.isAbstract()) {
            throw new BeanIsAbstractException(beanName);
        }
        
        // 4️⃣ 处理LookupMethod替换(@Lookup注解)
        if (mbd.hasMethodOverrides()) {
            // 创建代理类,处理lookup-method和replace-method
            return resolveBeforeInstantiation(beanName, mbd);
        }
        
        // 5️⃣ 真正创建Bean实例
        Object beanInstance = doCreateBean(beanName, mbd, args);
        return beanInstance;
        
    } catch (BeanCreationException ex) {
        throw ex;
    }
}

/**
 * 真正创建Bean的方法
 */
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    
    // 1️⃣ 创建BeanWrapper(包装器)
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 单例模式下,从缓存获取之前创建的FactoryBean
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    
    if (instanceWrapper == null) {
        // 2️⃣ 实例化Bean(使用构造方法或工厂方法)
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanClass = instanceWrapper.getWrappedClass();
    
    // 3️⃣ 提前暴露Bean(用于解决循环依赖)
    boolean earlySingletonExposure = mbd.isSingleton() && 
                                    mbd.allowCircularReferences() &&
                                    isSingletonCurrentlyInCreation(beanName);
    if (earlySingletonExposure) {
        // 添加到三级缓存:singletonFactories
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    
    // 4️⃣ 属性填充(依赖注入)
    populateBean(beanName, mbd, instanceWrapper);
    
    // 5️⃣ 初始化Bean(执行Aware接口、init-method等)
    bean = initializeBean(beanName, bean, mbd);
    
    // 6️⃣ 处理循环依赖
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            // 循环依赖处理...
        }
    }
    
    // 7️⃣ 注册DisposableBean(销毁回调)
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
    
    return bean;
}

Bean创建流程图:

┌─────────────────────────────────────────────────────────────────────┐
│                      doCreateBean 流程图                             │
│                                                                      │
│   createBeanInstance()  ◄── 实例化Bean                               │
│         │                                                            │
│         ▼                                                            │
│   ┌─────────────────────────────────────┐                           │
│   │      构造方法选择策略                │                           │
│   │                                      │                           │
│   │  1.@Autowired构造方法?           │                           │
│   │     → 使用该构造方法                 │                           │
│   │                                      │                           │
│   │  2. 只有一个构造方法?               │                           │
│   │     → 使用该构造方法                 │                           │
│   │                                      │                           │
│   │  3. 有多个构造方法?                 │                           │
│   │     → 使用无参构造方法(有就报错)   │                           │
│   └─────────────────────────────────────┘                           │
│         │                                                            │
│         ▼                                                            │
│   populateBean()  ◄── 属性填充(依赖注入)                           │
│         │                                                            │
│         ▼                                                            │
│   ┌─────────────────────────────────────┐                           │
│   │         依赖注入方式                 │                           │
│   │                                      │                           │
│   │  @Autowired                          │                           │
│   │      ├── @Autowired on Field         │                           │
│   │      │    → 反射注入字段值            │                           │
│   │      │                                │                           │
│   │      ├── @Autowired on Setter        │                           │
│   │      │    → 调用setter方法注入        │                           │
│   │      │                                │                           │
│   │      └── @Autowired on Constructor   │                           │
│   │           → 构造方法注入              │                           │
│   │                                      │                           │
│   │  @Resource (javax.annotation)        │                           │
│   │      → byName 优先                   │                           │
│   │                                      │                           │
│   │  @Value                               │                           │
│   │      → 注入普通值/SpEL                │                           │
│   └─────────────────────────────────────┘                           │
│         │                                                            │
│         ▼                                                            │
│   initializeBean()  ◄── 初始化Bean                                  │
│         │                                                            │
│         ▼                                                            │
│   ┌─────────────────────────────────────┐                           │
│   │         初始化流程                   │                           │
│   │                                      │                           │
│   │  1. Aware接口处理                    │                           │
│   │     BeanNameAware → setBeanName()    │                           │
│   │     BeanFactoryAware → setBeanFactory│                           │
│   │     ApplicationContextAware →        │                           │
│   │         setApplicationContext()       │                           │
│   │                                      │                           │
│   │  2. BeanPostProcessor.postProcessBeforeInitialization   │       │
│   │                                      │                           │
│   │  3. InitializingBean.afterPropertiesSet()               │       │
│   │     或 @PostConstruct               │                           │
│   │                                      │                           │
│   │  4. BeanPostProcessor.postProcessAfterInitialization   │       │
│   │                                      │                           │
│   │  5. Bean已准备就绪                  │                           │
│   └─────────────────────────────────────┘                           │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

三、Bean生命周期:完整流程图解

3.1 生命周期全图

┌─────────────────────────────────────────────────────────────────────────────┐
│                          Bean 完整生命周期                                   │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐ │
│   │                        1. BeanDefinition阶段                         │ │
│   │                                                                      │ │
│   │   扫描class → 解析注解 → 生成BeanDefinition → 注册到BeanFactory     │ │
│   └─────────────────────────────────────────────────────────────────────┘ │
│                                      │                                    │
│                                      ▼                                    │
│   ┌─────────────────────────────────────────────────────────────────────┐ │
│   │                        2. Bean实例化阶段                             │ │
│   │                                                                      │ │
│   │   BeanWrapper创建 → 构造方法选择 → 实例化Bean                       │ │
│   └─────────────────────────────────────────────────────────────────────┘ │
│                                      │                                    │
│                                      ▼                                    │
│   ┌─────────────────────────────────────────────────────────────────────┐ │
│   │                        3. 属性填充阶段                               │ │
│   │                                                                      │ │
│   │   @Autowired注入 → @Value注入 → @Resource注入                      │ │
│   └─────────────────────────────────────────────────────────────────────┘ │
│                                      │                                    │
│                                      ▼                                    │
│   ┌─────────────────────────────────────────────────────────────────────┐ │
│   │                        4. 初始化阶段                                │ │
│   │                                                                      │ │
│   │   BeanNameAware → BeanFactoryAware → ApplicationContextAware       │ │
│   │          ↓                                                           │ │
│   │   postProcessBeforeInitialization                                   │ │
│   │          ↓                                                           │ │
│   │   @PostConstruct / afterPropertiesSet()                            │ │
│   │          ↓                                                           │ │
│   │   postProcessAfterInitialization                                     │ │
│   │          ↓                                                           │ │
│   │   初始化完成,Bean可用                                                │ │
│   └─────────────────────────────────────────────────────────────────────┘ │
│                                      │                                    │
│                                      ▼                                    │
│   ┌─────────────────────────────────────────────────────────────────────┐ │
│   │                        5. 销毁阶段                                  │ │
│   │                                                                      │ │
│   │   @PreDestroy / destroy() / DisposableBean.destroy()              │ │
│   └─────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

3.2 生命周期代码演示

/**
 * 完整演示Bean生命周期的各个阶段
 */
@Component
@Scope("singleton")
public class UserService implements InitializingBean, DisposableBean, 
                                     BeanNameAware, BeanFactoryAware {
    
    @Autowired
    private UserDao userDao;
    
    @Value("${app.name:default}")
    private String appName;
    
    // ==================== 1. 构造方法 ====================
    public UserService() {
        System.out.println("1️⃣ UserService 构造方法执行");
    }
    
    // ==================== 2. 属性注入 ====================
    @Autowired
    public void setUserDao(UserDao userDao) {
        System.out.println("2️⃣ UserDao 依赖注入: " + userDao);
        this.userDao = userDao;
    }
    
    @PostConstruct
    public void init() {
        System.out.println("4️⃣ @PostConstruct 初始化方法执行");
    }
    
    @PreDestroy
    public void cleanup() {
        System.out.println("7️⃣ @PreDestroy 销毁前方法执行");
    }
    
    // ==================== 3. Aware接口 ====================
    @Override
    public void setBeanName(String name) {
        System.out.println("3️⃣ BeanNameAware.setBeanName: " + name);
    }
    
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3️⃣ BeanFactoryAware.setBeanFactory: " + beanFactory);
    }
    
    // ==================== 4. InitializingBean ====================
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5️⃣ InitializingBean.afterPropertiesSet");
    }
    
    // ==================== 5. DisposableBean ====================
    @Override
    public void destroy() throws Exception {
        System.out.println("6️⃣ DisposableBean.destroy");
    }
    
    // ==================== 业务方法 ====================
    public void save(User user) {
        userDao.save(user);
    }
}

/**
 * 演示BeanPostProcessor
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
            throws BeansException {
        System.out.println("🔄 postProcessBeforeInitialization: " + beanName);
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) 
            throws BeansException {
        System.out.println("🔄 postProcessAfterInitialization: " + beanName);
        return bean;
    }
}

输出顺序:

1️⃣ UserService 构造方法执行
3️⃣ BeanNameAware.setBeanName: userService
3️⃣ BeanFactoryAware.setBeanFactory: org.springframework...
🔄 postProcessBeforeInitialization: userService
2️⃣ UserDao 依赖注入: com.example.dao.UserDao@12345678
4️⃣ @PostConstruct 初始化方法执行
5️⃣ InitializingBean.afterPropertiesSet
🔄 postProcessAfterInitialization: userService
...
容器关闭:
6️⃣ DisposableBean.destroy
7️⃣ @PreDestroy 销毁前方法执行

四、依赖注入:三种方式深度解析

4.1 构造方法注入 vs Setter注入 vs 字段注入

/**
 * 三种依赖注入方式对比
 */
@Service
public class UserService {
    
    private UserDao userDao;
    private String appName;
    
    // ==================== 1. 构造方法注入(推荐)====================
    @Autowired
    public UserService(UserDao userDao, @Value("${app.name}") String appName) {
        // 优点:
        // 1. 强制依赖,编译时就检查
        // 2. 可以设置为final
        // 3. 便于单元测试(直接new)
        // 4. 循环依赖检测
        this.userDao = userDao;
        this.appName = appName;
    }
    
    // ==================== 2. Setter注入(可选依赖)====================
    private CacheService cacheService;
    
    @Autowired(required = false)  // required = false表示可选
    public void setCacheService(CacheService cacheService) {
        // 优点:
        // 1. 可选依赖
        // 2. 可以在运行时替换(测试场景)
        this.cacheService = cacheService;
    }
    
    // ==================== 3. 字段注入(不推荐)====================
    @Autowired
    private LogService logService;  // ❌ 不推荐
    
    // 为什么不推荐字段注入?
    // 1. 无法设置为final
    // 2. 难以单元测试(需要反射或Spring Test)
    // 3. 违反单一职责原则
    // 4. 无法注入编译时常量
}

4.2 @Autowired vs @Resource 区别

@Service
public class UserService {
    
    // @Autowired vs @Resource 区别
    // ================================
    
    // 1. @Autowired
    //    - 来源:Spring
    //    - 默认按byType注入
    //    - 可以配合@Qualifier按name注入
    //    - required属性控制是否必需
    @Autowired
    @Qualifier("userDaoImpl")  // 指定Bean名称
    private UserDao userDao1;
    
    // 2. @Resource
    //    - 来源:JSR-250(Java标准)
    //    - 默认按byName注入
    //    - name属性指定Bean名称
    //    - 没有required属性
    @Resource(name = "userDaoImpl")
    private UserDao userDao2;
    
    // 3. @Inject
    //    - 来源:JSR-330
    //    - 类似@Autowired
    //    - 需要导入javax.inject包
    @Inject
    private UserDao userDao3;
}

4.3 循环依赖:三级缓存揭秘

什么是循环依赖?

// 循环依赖示例
@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;  // 依赖B
}

@Service
public class ServiceB {
    @Autowired
    private ServiceA serviceA;  // 又依赖A!循环了!
}

Spring如何解决循环依赖?

Spring使用三级缓存来解决这个问题:

┌─────────────────────────────────────────────────────────────────────┐
│                      三级缓存解决循环依赖                            │
│                                                                      │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │  一级缓存:singletonObjects                                 │   │
│   │  - 完全初始化好的Bean                                      │   │
│   │  - 可以直接使用                                            │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                              ▲                                       │
│                              │                                       │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │  二级缓存:earlySingletonObjects                           │   │
│   │  - 提前曝光的Bean(未完全初始化)                          │   │
│   │  - 正在创建中                                               │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                              ▲                                       │
│                              │                                       │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │  三级缓存:singletonFactories                               │   │
│   │  - Bean工厂(用于创建早期Bean的引用)                       │   │
│   │  - ObjectFactory<?>                                        │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

解决过程图解:

┌─────────────────────────────────────────────────────────────────────┐
                      循环依赖解决过程                                
                                                                      
   假设创建ServiceA,ServiceA依赖ServiceB,ServiceB又依赖ServiceA    
                                                                      
   步骤1:开始创建ServiceA                                           
   ┌─────────────────────────────────────────────────────────────┐   
     创建ServiceA                                                  
     1️⃣ 调用构造方法                                              
     2️⃣ 创建原始对象A(未填充属性)                               
     3️⃣ 放入三级缓存singletonFactories                            
        {"serviceA": ObjectFactory<ServiceA>}                     
   └─────────────────────────────────────────────────────────────┘   
                                                                     
                                                                     
   步骤2:填充ServiceA的属性,发现依赖ServiceB                        
   ┌─────────────────────────────────────────────────────────────┐   
     填充@Autowired ServiceB                                       
      尝试获取ServiceB                                            
      ServiceB还没创建!需要创建ServiceB                          
   └─────────────────────────────────────────────────────────────┘   
                                                                     
                                                                     
   步骤3:开始创建ServiceB                                           
   ┌─────────────────────────────────────────────────────────────┐   
     创建ServiceB                                                  
     1️⃣ 调用构造方法                                              
     2️⃣ 创建原始对象B(未填充属性)                               
     3️⃣ 放入三级缓存singletonFactories                            
        {"serviceB": ObjectFactory<ServiceB>}                     
   └─────────────────────────────────────────────────────────────┘   
                                                                     
                                                                     
   步骤4:填充ServiceB的属性,发现依赖ServiceA                        
   ┌─────────────────────────────────────────────────────────────┐   
     填充@Autowired ServiceA                                       
      尝试获取ServiceA                                            
      从三级缓存获取ServiceA的ObjectFactory                       
      调用getObject()获取早期引用                                 
      放入二级缓存earlySingletonObjects                          
      从三级缓存移除                                              
      ServiceB填充完成                                           
   └─────────────────────────────────────────────────────────────┘   
                                                                     
                                                                     
   步骤5ServiceB创建完成                                           
   ┌─────────────────────────────────────────────────────────────┐   
     ServiceB填充完成                                              
      放入一级缓存singletonObjects                               
      从二级/三级缓存移除                                          
   └─────────────────────────────────────────────────────────────┘   
                                                                     
                                                                     
   步骤6:回到ServiceA,填充ServiceB                                  
   ┌─────────────────────────────────────────────────────────────┐   
     从一级缓存获取ServiceB                                        
      ServiceA填充完成                                            
      放入一级缓存singletonObjects                               
   └─────────────────────────────────────────────────────────────┘   
                                                                     
                                                                     
   完成!循环依赖解决                                                
                                                                      
└─────────────────────────────────────────────────────────────────────┘

为什么需要三级缓存?

// 二级缓存不够吗?
// 答案:不够!因为需要支持AOP代理

// 假设ServiceA有AOP增强
@Service
public class ServiceA {
    @Transactional
    public void doSomething() { }
}

// 创建过程需要增强:
// 1. ServiceA原始对象创建
// 2. 需要知道是否需要创建代理
// 3. 如果需要,创建代理对象

// 三级缓存的设计:
// - 一级缓存:完全初始化好的Bean(可能已经是代理)
// - 二级缓存:早期暴露的Bean(可能是代理)
// - 三级缓存:Bean工厂(延迟创建代理)

// 好处:
// 1. 延迟代理对象的创建(性能优化)
// 2. 允许在Bean创建过程中动态决定是否创建代理
// 3. 完美解决循环依赖 + AOP问题

五、AOP切面编程:源码深度解析

5.1 AOP核心概念

┌─────────────────────────────────────────────────────────────────────┐
│                         AOP核心概念                                  │
│                                                                      │
│   ┌─────────┐                                                       │
│   │  切面   │  Aspect = 切入点 + 通知                                │
│   │ Aspect │  定义:在哪个时机(通知)做什么(增强逻辑)              │
│   └─────────┘                                                       │
│          │                                                          │
│          │ 包含                                                         │
│          ▼                                                          │
│   ┌─────────┐     ┌─────────┐     ┌─────────┐     ┌─────────┐       │
│   │  切入点  │     │  通知   │     │  目标   │     │  代理   │       │
│   │Pointcut│     │ Advice  │     │ Target  │     │ Proxy   │       │
│   │  哪里切 │     │  何时通知│     │  业务类  │     │  增强后  │       │
│   └─────────┘     └─────────┘     └─────────┘     └─────────┘       │
│                                                                      │
│   通知类型:                                                         │
│   ┌────────────────────────────────────────────────────────────┐    │
│   │  @Before   - 前置通知:方法执行前                           │    │
│   │  @After    - 后置通知:方法执行后(无论是否异常)            │    │
│   │  @AfterReturning - 返回通知:方法正常返回后                 │    │
│   │  @AfterThrowing  - 异常通知:方法抛出异常后                 │    │
│   │  @Around   - 环绕通知:方法执行前后(可以控制是否执行)      │    │
│   └────────────────────────────────────────────────────────────┘    │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

5.2 实战:自定义日志切面

/**
 * 日志切面:记录方法调用信息
 */
@Aspect
@Component
@Slf4j
public class LoggingAspect {
    
    /**
     * 定义切入点:所有Controller层的public方法
     */
    @Pointcut("execution(public * com.example.controller..*.*(..))")
    public void controllerPointcut() {}
    
    /**
     * 定义切入点:所有Service层的save/update/delete方法
     */
    @Pointcut("execution(* com.example.service..*.save*(..)) || " +
              "execution(* com.example.service..*.update*(..)) || " +
              "execution(* com.example.service..*.delete*(..))")
    public void modifyOperationPointcut() {}
    
    /**
     * 前置通知:记录方法开始
     */
    @Before("controllerPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        // 获取方法签名
        Signature signature = joinPoint.getSignature();
        // 获取类名.方法名
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
        // 获取参数
        Object[] args = joinPoint.getArgs();
        
        log.info("➡️ 方法开始: {},参数: {}", methodName, Arrays.toString(args));
    }
    
    /**
     * 返回通知:记录方法返回值
     */
    @AfterReturning(pointcut = "controllerPointcut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        Signature signature = joinPoint.getSignature();
        log.info("✅ 方法返回: {}.{},结果: {}", 
            signature.getDeclaringTypeName(), 
            signature.getName(),
            result);
    }
    
    /**
     * 异常通知:记录方法异常
     */
    @AfterThrowing(pointcut = "controllerPointcut()", throwing = "exception")
    public void doAfterThrowing(JoinPoint joinPoint, Exception exception) {
        Signature signature = joinPoint.getSignature();
        log.error("❌ 方法异常: {}.{},异常: {}", 
            signature.getDeclaringTypeName(), 
            signature.getName(),
            exception.getMessage(), 
            exception);
    }
    
    /**
     * 环绕通知:性能监控
     */
    @Around("modifyOperationPointcut()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        // 执行目标方法
        Object result = point.proceed();
        
        long endTime = System.currentTimeMillis();
        String methodName = point.getSignature().getName();
        
        log.info("⏱️ 业务操作: {},耗时: {}ms", methodName, endTime - startTime);
        
        return result;
    }
}

5.3 事务切面:@Transactional原理

/**
 * @Transactional 原理
 * 
 * Spring事务基于AOP实现,核心类:TransactionInterceptor
 */
@Service
public class TransactionalService {
    
    @Transactional(rollbackFor = Exception.class)
    public void transfer(String from, String to, BigDecimal amount) {
        // 这些操作在同一个事务中
        accountDao.decrease(from, amount);    // 扣款
        accountDao.increase(to, amount);      // 存款
        // 如果发生异常,整个事务回滚
    }
}

/**
 * 自定义事务管理器切面(简化版)
 */
@Aspect
@Component
public class TransactionAspect {
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    @Around("@annotation(Transactional)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 1️⃣ 获取事务定义
        TransactionDefinition definition = new DefaultTransactionDefinition();
        
        // 2️⃣ 获取或创建事务
        TransactionStatus status = transactionManager.getTransaction(definition);
        
        try {
            // 3️⃣ 执行目标方法
            Object result = point.proceed();
            
            // 4️⃣ 提交事务
            transactionManager.commit(status);
            
            return result;
            
        } catch (Exception e) {
            // 5️⃣ 回滚事务
            transactionManager.rollback(status);
            throw e;
        }
    }
}

六、动态代理:JDK vs CGLIB

6.1 为什么需要代理?

┌─────────────────────────────────────────────────────────────────────┐
│                         代理模式原理                                 │
│                                                                      │
│   ┌─────────────────┐              ┌─────────────────┐              │
│   │    客户端       │              │    目标对象      │              │
│   │   (Client)     │              │   (Target)     │              │
│   └────────┬────────┘              └─────────────────┘              │
│            │                                                          │
│            │ 调用                                                     │
│            ▼                                                          │
│   ┌─────────────────┐                                               │
│   │     代理对象     │                                               │
│   │    (Proxy)     │                                               │
│   │                  │                                               │
│   │ 1. 前置增强      │                                               │
│   │ 2. 调用目标方法  │                                               │
│   │ 3. 后置增强      │                                               │
│   │ 4. 返回结果      │                                               │
│   └────────┬────────┘                                               │
│            │                                                          │
│            ▼                                                          │
│   ┌─────────────────┐                                               │
│   │    目标对象      │                                               │
│   │   (Target)     │                                               │
│   └─────────────────┘                                               │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

6.2 JDK动态代理:基于接口

原理:

/**
 * JDK动态代理演示
 * 
 * 核心类:java.lang.reflect.Proxy
 * 要求:目标类必须实现接口
 */
public class JdkProxyDemo {
    
    public static void main(String[] args) {
        
        // 1️⃣ 定义目标对象(必须实现接口)
        UserService target = new UserServiceImpl();
        
        // 2️⃣ 创建InvocationHandler
        InvocationHandler handler = (proxy, method, methodArgs) -> {
            // 前置增强
            System.out.println(">>> 前置逻辑开始");
            long startTime = System.currentTimeMillis();
            
            // 3️⃣ 调用目标方法
            Object result = method.invoke(target, methodArgs);
            
            // 后置增强
            long endTime = System.currentTimeMillis();
            System.out.println("<<< 后置逻辑结束,耗时:" + (endTime - startTime) + "ms");
            
            return result;
        };
        
        // 4️⃣ 创建代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),  // 类加载器
            target.getClass().getInterfaces(),     // 实现的接口
            handler                               // 处理逻辑
        );
        
        // 5️⃣ 使用代理对象(与使用原对象完全相同)
        proxy.save(new User());
        proxy.update(new User());
    }
}

/**
 * 接口定义
 */
interface UserService {
    void save(User user);
    void update(User user);
}

/**
 * 实现类
 */
class UserServiceImpl implements UserService {
    @Override
    public void save(User user) {
        System.out.println("UserServiceImpl.save 执行");
    }
    
    @Override
    public void update(User user) {
        System.out.println("UserServiceImpl.update 执行");
    }
}

生成的代理类结构:

// 生成的代理类(伪代码)
public class $Proxy0 implements UserService {
    
    private InvocationHandler h;
    
    public $Proxy0(InvocationHandler h) {
        this.h = h;
    }
    
    @Override
    public void save(User user) {
        // 调用InvocationHandler
        h.invoke(this, saveMethod, new Object[]{user});
    }
    
    @Override
    public void update(User user) {
        h.invoke(this, updateMethod, new Object[]{user});
    }
}

6.3 CGLIB代理:基于继承

原理:

/**
 * CGLIB动态代理演示
 * 
 * 核心类:net.sf.cglib.proxy.Enhancer
 * 要求:目标类不能是final
 * 原理:继承目标类,重写方法
 */
public class CglibProxyDemo {
    
    public static void main(String[] args) {
        
        // 1️⃣ 创建Enhancer
        Enhancer enhancer = new Enhancer();
        
        // 2️⃣ 设置父类(目标类)
        enhancer.setSuperclass(UserService.class);
        
        // 3️⃣ 设置回调
        enhancer.setCallbacks(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, 
                                   Object[] args, MethodProxy proxy) throws Throwable {
                // 前置增强
                System.out.println(">>> CGLIB 前置逻辑");
                long startTime = System.currentTimeMillis();
                
                // 调用父类方法(目标方法)
                // 方式1:proxy.invokeSuper() - 推荐
                Object result = proxy.invokeSuper(obj, args);
                
                // 方式2:proxy.invoke() - 慎用,可能导致死循环
                // Object result = proxy.invoke(target, args);
                
                // 后置增强
                long endTime = System.currentTimeMillis();
                System.out.println("<<< CGLIB 后置逻辑,耗时:" + (endTime - startTime));
                
                return result;
            }
        });
        
        // 4️⃣ 创建代理对象
        UserService proxy = (UserService) enhancer.create();
        
        // 5️⃣ 使用代理对象
        proxy.save(new User());
        proxy.update(new User());
    }
}

生成的代理类结构:

// 生成的代理类(伪代码)
public class UserServiceImpl$$EnhancerByCGLIB$$12345678 
        extends UserServiceImpl {
    
    private MethodInterceptor callback;
    
    // 构造函数
    public UserServiceImpl$$EnhancerByCGLIB$$12345678(MethodInterceptor callback) {
        this.callback = callback;
    }
    
    @Override
    public void save(User user) {
        // 调用拦截器
        MethodProxy proxy = ...;
        callback.intercept(this, saveMethod, new Object[]{user}, proxy);
    }
    
    @Override
    public void update(User user) {
        MethodProxy proxy = ...;
        callback.intercept(this, updateMethod, new Object[]{user}, proxy);
    }
}

6.4 两者对比

┌─────────────────────────────────────────────────────────────────────┐
│                      JDK代理 vs CGLIB代理                           │
│                                                                      │
│   ┌────────────────────┬────────────────────┐                        │
│   │      JDK代理       │      CGLIB代理    │                        │
│   ├────────────────────┼────────────────────┤                        │
│   │    依赖            │    JDK自带         │  net.sf.cglib        │
│   ├────────────────────┼────────────────────┤                        │
│   │    实现原理        │    接口实现        │  继承重写             │
│   ├────────────────────┼────────────────────┤                        │
│   │    要求            │    必须有接口      │  类不能是final        │
│   ├────────────────────┼────────────────────┤                        │
│   │    生成速度        │    快              │  慢                   │
│   ├────────────────────┼────────────────────┤                        │
│   │    运行速度        │    稍慢            │  快(直接调用)        │
│   │                    │  (反射调用)        │                        │
│   ├────────────────────┼────────────────────┤                        │
│   │    内存效率        │    高              │  低(创建子类)        │
│   ├────────────────────┼────────────────────┤                        │
│   │    适用场景        │    有接口的服务    │  无接口/类/ final类   │
│   └────────────────────┴────────────────────┘                        │
│                                                                      │
│   Spring默认策略:                                                    │
│   ┌─────────────────────────────────────────────────────────────┐    │
│   │                                                              │    │
│   │   目标类有接口?                                              │    │
│   │         │                                                    │    │
│   │    ┌────┴────┐                                              │    │
│   │    │ Yes     │ No                                          │    │
│   │    ▼         ▼                                              │    │
│   │ ┌──────┐  ┌──────┐                                          │    │
│   │ │ JDK  │  │CGLIB │                                          │    │
│   │ │ 代理 │  │ 代理 │                                          │    │
│   │ └──────┘  └──────┘                                          │    │
│   │                                                              │    │
│   │ 配置项:spring.aop.proxy-target-class=false  → 强制使用JDK   │    │
│   │         spring.aop.proxy-target-class=true   → 强制使用CGLIB│    │
│   │                                                              │    │
│   └─────────────────────────────────────────────────────────────┘    │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

6.5 Spring AOP代理创建流程

/**
 * AbstractAutowireCapableBeanFactory.createProxy() 简化版
 */
public class ProxyCreationFlow {
    
    // 入口:创建AOP代理
    protected Object createProxy(String beanName, RootBeanDefinition beanDefinition,
                                 Object bean, Set<String> targets) {
        
        // 1️⃣ 创建ProxyFactory
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(beanDefinition);
        
        // 2️⃣ 判断使用JdkDynamicProxy还是CglibAopProxy
        // 取决于proxyTargetClass属性和目标类是否有接口
        
        // 如果目标类有接口 && !proxyTargetClass → 使用JDK代理
        // 否则 → 使用CGLIB代理
        if (shouldProxyTargetClass(beanDefinition, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        
        // 3️⃣ 添加切面
        // @AspectJ标注的类会被解析成Advisor
        proxyFactory.addAdvisors(beanFactory.getAdvicesAndAdvisorsForBean(
            beanClass, beanName, null));
        
        // 4️⃣ 创建代理
        return proxyFactory.getProxy(getBeanClassLoader());
    }
    
    // 判断逻辑
    private boolean shouldProxyTargetClass(RootBeanDefinition beanDefinition, 
                                           String beanName) {
        // 1. 如果proxy-target-class=true,强制使用CGLIB
        if (beanDefinition.getAttribute("proxyTargetClass") == Boolean.TRUE) {
            return true;
        }
        
        // 2. 如果目标类有接口,使用JDK代理
        if (hasInterface(beanDefinition.getBeanClass())) {
            return false;
        }
        
        // 3. 否则使用CGLIB
        return true;
    }
}

七、Spring事务:传播行为深度解析

7.1 七种传播行为

/**
 * Spring事务传播行为
 * 
 * TransactionDefinition接口定义了7种传播行为
 */
public enum Propagation {
    
    /**
     * REQUIRED(默认)
     * 如果当前有事务,加入该事务
     * 如果当前没有事务,创建新事务
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 场景:A和B在同一个事务
        methodB();  // B加入A的事务
    }
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // 与A在同一个事务
    }
    
    /**
     * REQUIRES_NEW
     * 总是创建新事务
     * 如果当前有事务,挂起当前事务
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodC() {
        // 场景:C在独立事务中执行
        // 即使A的事务失败,C的事务不受影响
    }
    
    /**
     * SUPPORTS
     * 如果当前有事务,加入该事务
     * 如果当前没有事务,以非事务执行
     */
    
    /**
     * NOT_SUPPORTED
     * 如果当前有事务,挂起当前事务
     * 以非事务执行
     */
    
    /**
     * MANDATORY
     * 必须在事务中执行
     * 如果当前没有事务,抛异常
     */
    
    /**
     * NEVER
     * 必须在非事务中执行
     * 如果当前有事务,抛异常
     */
    
    /**
     * NESTED
     * 如果当前有事务,在嵌套事务中执行
     * 使用Savepoint机制(JDBC Savepoint)
     */
}

7.2 传播行为对比图

┌─────────────────────────────────────────────────────────────────────┐
│                      事务传播行为对比                                │
│                                                                      │
│   调用方(A)           被调用方(B)             结果                 │
│   ─────────           ─────────────           ──────                │
│                                                                      │
│   ┌─────────────┐     ┌─────────────┐                              │
│   │ @Transactional│     │ REQUIRED     │    ┌─────────────────┐    │
│   │   有事务     │────►│   (默认)     │────►│ AB在同一个事务  │    │
│   └─────────────┘     └─────────────┘     └─────────────────┘    │
│                                                                      │
│   ┌─────────────┐     ┌─────────────┐                              │
│   │ 无事务      │────►│ REQUIRED     │────►│ B创建新事务        │    │
│   └─────────────┘     └─────────────┘     └─────────────────┘    │
│                                                                      │
│   ┌─────────────┐     ┌─────────────┐                              │
│   │ @Transactional│     │REQUIRES_NEW │────►│ B在独立新事务执行  │    │
│   │   有事务     │────►│             │     │ A事务被挂起        │    │
│   └─────────────┘     └─────────────┘     └─────────────────┘    │
│                                                                      │
│   ┌─────────────┐     ┌─────────────┐                              │
│   │ @Transactional│     │   NESTED    │────►│ B在嵌套事务执行    │    │
│   │   有事务     │────►│  (Savepoint)│     │ A回滚,B部分回滚   │    │
│   └─────────────┘     └─────────────┘     └─────────────────┘    │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

八、实战:自定义Spring注解

8.1 自定义缓存注解

/**
 * 自定义缓存注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCacheable {
    
    // 缓存key
    String key();
    
    // 过期时间(秒)
    int expire() default 300;
}

/**
 * 缓存切面实现
 */
@Aspect
@Component
@Slf4j
public class MyCacheAspect {
    
    private Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
    
    @Around("@annotation(myCacheable)")
    public Object around(ProceedingJoinPoint point, MyCacheable myCacheable) 
            throws Throwable {
        
        String cacheKey = buildCacheKey(myCacheable.key(), point.getArgs());
        
        // 1️⃣ 尝试从缓存获取
        CacheEntry entry = cache.get(cacheKey);
        if (entry != null && !entry.isExpired()) {
            log.info("🔵 命中缓存: {}", cacheKey);
            return entry.getValue();
        }
        
        // 2️⃣ 缓存不存在或已过期,执行目标方法
        log.info("🔴 缓存未命中: {}", cacheKey);
        Object result = point.proceed();
        
        // 3️⃣ 写入缓存
        cache.put(cacheKey, new CacheEntry(result, myCacheable.expire()));
        
        return result;
    }
    
    private String buildCacheKey(String keyTemplate, Object[] args) {
        // 简单实现:替换{0}, {1}等占位符
        String result = keyTemplate;
        for (int i = 0; i < args.length; i++) {
            result = result.replace("{" + i + "}", 
                args[i] != null ? args[i].toString() : "null");
        }
        return result;
    }
    
    // 缓存条目
    private static class CacheEntry {
        private final Object value;
        private final long expireTime;
        
        public CacheEntry(Object value, int expireSeconds) {
            this.value = value;
            this.expireTime = System.currentTimeMillis() + expireSeconds * 1000L;
        }
        
        public Object getValue() { return value; }
        public boolean isExpired() { 
            return System.currentTimeMillis() > expireTime; 
        }
    }
}

/**
 * 使用自定义缓存注解
 */
@Service
public class UserService {
    
    @MyCacheable(key = "user:{0}", expire = 600)
    public User getUserById(Long id) {
        // 从数据库查询
        return userDao.findById(id);
    }
    
    @MyCacheable(key = "user:list:{0}:{1}", expire = 300)
    public List<User> getUsers(int page, int size) {
        return userDao.findAll(page, size);
    }
}

8.2 自定义限流注解

/**
 * 限流注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
    
    // 限流key
    String key() default "";
    
    // 时间窗口(秒)
    int window() default 1;
    
    // 最大请求数
    int maxRequests() default 100;
}

/**
 * 限流切面(基于令牌桶算法)
 */
@Aspect
@Component
@Slf4j
public class RateLimitAspect {
    
    private final Map<String, RateLimiter> limiters = new ConcurrentHashMap<>();
    
    @Around("@annotation(rateLimit)")
    public Object around(ProceedingJoinPoint point, RateLimit rateLimit) 
            throws Throwable {
        
        String key = getKey(rateLimit.key(), point);
        
        // 1️⃣ 获取或创建限流器
        RateLimiter limiter = limiters.computeIfAbsent(key, 
            k -> new RateLimiter(rateLimit.maxRequests(), rateLimit.window()));
        
        // 2️⃣ 尝试获取令牌
        if (!limiter.tryAcquire()) {
            log.warn("⚠️ 请求被限流: {}", key);
            throw new RuntimeException("请求太频繁,请稍后重试");
        }
        
        // 3️⃣ 执行目标方法
        return point.proceed();
    }
    
    private String getKey(String keyTemplate, ProceedingJoinPoint point) {
        if (StringUtils.isNotBlank(keyTemplate)) {
            return keyTemplate;
        }
        // 默认key:类名.方法名
        return point.getSignature().getDeclaringTypeName() + "." + 
               point.getSignature().getName();
    }
    
    /**
     * 简单限流器(固定窗口算法)
     */
    private static class RateLimiter {
        private final int maxRequests;
        private final long windowMillis;
        private final AtomicInteger count = new AtomicInteger(0);
        private volatile long windowStart = System.currentTimeMillis();
        
        public RateLimiter(int maxRequests, int windowSeconds) {
            this.maxRequests = maxRequests;
            this.windowMillis = windowSeconds * 1000L;
        }
        
        public boolean tryAcquire() {
            long now = System.currentTimeMillis();
            
            // 超过时间窗口,重置
            if (now - windowStart > windowMillis) {
                windowStart = now;
                count.set(0);
            }
            
            // 尝试递增计数
            return count.incrementAndGet() <= maxRequests;
        }
    }
}

/**
 * 使用限流注解
 */
@RestController
public class UserController {
    
    @RateLimit(key = "user:get", maxRequests = 100, window = 1)
    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }
    
    @RateLimit(key = "user:login", maxRequests = 10, window = 60)
    @PostMapping("/login")
    public String login(@RequestBody LoginRequest request) {
        return userService.login(request);
    }
}

九、面试重点总结

9.1 IOC相关面试题

Q1: Spring容器启动流程是什么?

1. prepareRefresh() - 准备刷新
2. obtainFreshBeanFactory() - 获取BeanFactory
3. prepareBeanFactory() - 准备BeanFactory
4. postProcessBeanFactory() - 后置处理BeanFactory
5. invokeBeanFactoryPostProcessors() - 执行BeanFactory后置处理器
6. registerBeanPostProcessors() - 注册Bean后置处理器
7. initMessageSource() - 初始化消息源
8. initApplicationEventMulticaster() - 初始化事件广播器
9. onRefresh() - 子类扩展
10. registerListeners() - 注册监听器
11. finishBeanFactoryInitialization() - 初始化所有单例Bean
12. finishRefresh() - 完成刷新

Q2: Bean的生命周期有哪些?

1. 实例化(构造方法)
2. 属性填充(依赖注入)
3. Aware接口注入
   - BeanNameAware
   - BeanFactoryAware
   - ApplicationContextAware
4. BeanPostProcessor.postProcessBeforeInitialization()
5. @PostConstruct
6. InitializingBean.afterPropertiesSet()
7. BeanPostProcessor.postProcessAfterInitialization()
8. Bean就绪
9. @PreDestroy
10. DisposableBean.destroy()

Q3: Spring如何解决循环依赖?

使用三级缓存:
- 一级缓存:完全初始化好的Bean
- 二级缓存:提前曝光的Bean(未完全初始化)
- 三级缓存:Bean工厂

流程:
1. 创建A,放入三级缓存
2. 填充A的属性,发现依赖B
3. 创建B,放入三级缓存
4. 填充B的属性,发现依赖A
5. 从三级缓存获取A的工厂,创建早期A
6. B创建完成,放入一级缓存
7. A填充B成功,创建完成

Q4: @Autowired和@Resource的区别?

| 特性       | @Autowired        | @Resource             |
|------------|-------------------|----------------------|
| 来源       | Spring            | JSR-250 (Java标准)   |
| 默认方式   | byType            | byName               |
| 配合注解   | @Qualifier        | name属性             |
| required   | 支持              | 不支持               |

9.2 AOP相关面试题

Q5: AOP的代理机制是什么?

Spring AOP使用代理模式,有两种实现:

1. JDK动态代理(默认)
   - 需要目标类实现接口
   - 代理类实现相同接口
   - 调用InvocationHandler

2. CGLIB代理
   - 继承目标类
   - 重写方法
   - 使用MethodInterceptor

选择策略:
- 目标类有接口 → JDK代理
- 目标类无接口 → CGLIB代理
- proxyTargetClass=true → 强制CGLIB

Q6: AOP通知的执行顺序?

正常流程:
@Before → 目标方法 → @AfterReturning@After

异常流程:
@Before → 目标方法 → @AfterThrowing@After

环绕通知:
@Around(前置) → 目标方法 → @Around(后置)

Q7: Spring事务的传播行为有哪些?

REQUIRED(默认):有事务加入,无事务创建
REQUIRES_NEW:始终创建新事务
SUPPORTS:有事务加入,无事务非事务执行
NOT_SUPPORTED:挂起事务,非事务执行
MANDATORY:必须在事务中,否则抛异常
NEVER:必须在非事务中,否则抛异常
NESTED:嵌套事务(Savepoint

9.3 知识图谱

┌──────────────────────────────────────────────────────────────────────────┐
                         Spring IOC/AOP 知识图谱                          
                                                                          
  ┌────────────────────────────────────────────────────────────────────┐ 
                           IOC容器                                      
                                                                         
    ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐            
     refresh    BeanDef     依赖注入    循环依赖             
     启动流程    注册解析     三种方式    三级缓存             
    └──────────┘  └──────────┘  └──────────┘  └──────────┘            
  └────────────────────────────────────────────────────────────────────┘ 
                                                                        
                                                                        
  ┌────────────────────────────────────────────────────────────────────┐ 
                           Bean生命周期                                 
                                                                         
    实例化  属性填充  Aware注入  初始化  销毁                       
                                                                         
    关键扩展点:BeanPostProcessorInitializingBeanDisposableBean     
  └────────────────────────────────────────────────────────────────────┘ 
                                                                        
                                                                        
  ┌────────────────────────────────────────────────────────────────────┐ 
                           AOP切面编程                                   
                                                                         
    ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐            
     切入点      通知类型    JDK代理     CGLIB代理             
     @Pointcut   5种通知     基于接口    基于继承              
    └──────────┘  └──────────┘  └──────────┘  └──────────┘            
  └────────────────────────────────────────────────────────────────────┘ 
                                                                        
                                                                        
  ┌────────────────────────────────────────────────────────────────────┐ 
                           事务管理                                     
                                                                         
    ┌──────────┐  ┌──────────┐  ┌──────────┐                           
     @Transactional 传播行为    事务实现                            
    └──────────┘  └──────────┘  └──────────┘                           
  └────────────────────────────────────────────────────────────────────┘ 
                                                                          
└──────────────────────────────────────────────────────────────────────────┘

结语

这篇文章我们从Spring IOC/AOP的源码层面进行了深度剖析,涵盖了:

核心要点回顾:

  1. IOC容器启动refresh()方法是入口,核心流程包括BeanDefinition加载、Bean实例化、属性填充、初始化等
  2. Bean生命周期:从构造方法到销毁回调,共10个关键步骤
  3. 依赖注入:构造方法注入(推荐)、Setter注入、字段注入三种方式
  4. 循环依赖:三级缓存完美解决,核心是提前暴露Bean
  5. AOP原理:JDK代理 vs CGLIB代理,Spring根据情况自动选择
  6. 事务传播:7种传播行为解决嵌套调用问题
  7. 自定义注解:结合AOP实现缓存、限流等高级功能

Spring的设计之美在于解耦和扩展。希望这篇文章能帮助大家理解框架的底层原理,写出更优雅的代码!


本文首发于掘金,同步更新于CSDN

更多优质内容,欢迎关注我的博客