首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从Spring源码解析到手写核心组件:深入IoC容器与AOP实现内幕

从Spring源码解析到手写核心组件:深入IoC容器与AOP实现内幕

原创
作者头像
用户12678265
发布2026-08-09 14:05:43
发布2026-08-09 14:05:43
1990
举报

从Spring源码解析到手写核心组件:深入IoC容器与AOP实现内幕

一、为什么必须深入Spring源码?

Spring框架自2003年问世以来,已成为Java企业级开发的事实标准。然而,许多开发者长期处于“会用Spring却不懂Spring”的尴尬境地——当@Autowired突然失效、事务注解不回滚时,只能盲目搜索解决方案。真正的高手,不仅要会用框架,更要理解框架的设计哲学与实现原理。

Spring的核心设计思想可以概括为三点:控制反转(IoC)、依赖注入(DI)和面向切面编程(AOP)。本文将沿着“源码解析→原理剖析→手写实现”的路径,带你彻底吃透Spring的两大核心组件。

二、Spring IoC容器源码深度解析

2.1 BeanDefinition:一切Bean的起点

在Spring中,所有Bean的配置信息都被抽象为BeanDefinition对象。它是Bean的“蓝图”或“配方”,包含了类名、作用域、依赖关系、初始化方法、销毁方法等所有元数据。

代码语言:javascript
复制
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    // 获取/设置Bean的类名
    String getBeanClassName();
    void setBeanClassName(String beanClassName);
    
    // 获取/设置作用域
    String getScope();
    void setScope(String scope);
    
    // 检查是否是单例/原型
    boolean isSingleton();
    boolean isPrototype();
    
    // 检查是否延迟初始化
    boolean isLazyInit();
    
    // 获取属性值
    PropertyValues getPropertyValues();
}

BeanDefinition接口的设计体现了Spring“约定优于配置”的理念。无论是XML配置、注解配置还是Java配置,最终都会被解析为统一的BeanDefinition对象。

2.2 容器启动六步流程

Spring IoC容器的启动入口是refresh()方法——无论是ClassPathXmlApplicationContext还是AnnotationConfigApplicationContext,最终都会调用这个方法。

代码语言:javascript
复制
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备刷新上下文
        prepareRefresh();
        
        // 2. 创建并准备BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
        // 3. 准备BeanFactory(设置类加载器、后置处理器等)
        prepareBeanFactory(beanFactory);
        
        // 4. 允许子类对BeanFactory进行后置处理
        postProcessBeanFactory(beanFactory);
        
        // 5. 调用BeanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(beanFactory);
        
        // 6. 注册BeanPostProcessor
        registerBeanPostProcessors(beanFactory);
        
        // 7. 初始化消息源
        initMessageSource();
        
        // 8. 初始化事件广播器
        initApplicationEventMulticaster();
        
        // 9. 初始化特定子类中的特殊Bean
        onRefresh();
        
        // 10. 注册监听器
        registerListeners();
        
        // 11. 实例化所有非懒加载的单例Bean
        finishBeanFactoryInitialization(beanFactory);
        
        // 12. 完成刷新,发布事件
        finishRefresh();
    }
}

容器启动的核心逻辑是:先扫描配置生成BeanDefinition,再注册BeanPostProcessor提供扩展点,最后实例化所有非懒加载的单例Bean

2.3 三级缓存:循环依赖的破解之道

循环依赖是指A依赖B、B依赖A的情况。Spring通过三级缓存巧妙解决了这一问题:

  • 一级缓存 singletonObjects:存放完全创建好的单例Bean
  • 二级缓存 earlySingletonObjects:存放已完成实例化但未完成属性注入的对象
  • 三级缓存 singletonFactories:存放提前暴露的单例工厂

代码语言:javascript
复制
public class DefaultSingletonBeanRegistry {
    // 一级缓存:单例池
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    // 二级缓存:早期单例对象
    private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
    
    // 三级缓存:单例工厂
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 先从一级缓存获取
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 从二级缓存获取
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                synchronized (this.singletonObjects) {
                    // 从三级缓存获取ObjectFactory并创建早期对象
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        // 升级到二级缓存
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 移除三级缓存
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
}

三级缓存解决循环依赖的核心逻辑是:当A创建时,先将A的ObjectFactory放入三级缓存,然后A进行属性注入时发现依赖B,于是去创建B;B创建时发现依赖A,从三级缓存获取A的ObjectFactory创建A的早期引用并注入B;B完成创建后,A再从缓存获取已完成的B完成注入。

三、Spring AOP实现机制剖析

3.1 代理模式的选择逻辑

Spring AOP基于动态代理实现,分为JDK动态代理和CGLIB代理两种方式:

  • 目标类实现了接口 → 使用JDK动态代理
  • 目标类未实现接口 → 使用CGLIB生成子类代理

3.2 核心源码解析

AOP的核心在ProxyFactory类,它负责创建代理对象,构建拦截器链,每个通知(Advice)被转换为方法拦截器(MethodInterceptor)。

代码语言:javascript
复制
// Spring AOP代理创建的核心逻辑(简化)
public class ProxyFactory {
    private Object target;
    private List<Advice> advices;
    
    public Object getProxy() {
        // 判断使用哪种代理方式
        if (hasInterfaces(target)) {
            return createJdkProxy();
        } else {
            return createCglibProxy();
        }
    }
    
    private Object createJdkProxy() {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    // 构建拦截器链
                    List<MethodInterceptor> interceptors = getInterceptors(method);
                    // 责任链模式执行
                    return new ReflectiveMethodInvocation(target, method, args, interceptors).proceed();
                }
            }
        );
    }
}

Pointcut表达式解析是另一个关键实现细节。Spring使用AspectJ的表达式语法,但实现了自己的解析逻辑,在匹配方法时会考虑方法的修饰符、返回类型、方法名、参数类型等因素。

四、手写实现Spring核心组件

4.1 手写简易IoC容器

理解了源码设计,我们可以手写一个精简版IoC容器,核心功能包括:包扫描、Bean实例化、依赖注入。

代码语言:javascript
复制
/**
 * 自定义注解 - 标记需要被容器管理的类
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
    String value() default "";
}

/**
 * 自定义注解 - 依赖注入
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

/**
 * 简易IoC容器
 */
public class SimpleApplicationContext {
    // 单例池(一级缓存)
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    // Bean定义映射
    private final Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>();
    // 正在创建的Bean集合(用于检测循环依赖)
    private final Set<String> singletonsCurrentlyInCreation = new HashSet<>();
    
    private String basePackage;
    
    public SimpleApplicationContext(String basePackage) {
        this.basePackage = basePackage;
        refresh();
    }
    
    /**
     * 容器刷新 - 核心方法
     */
    public void refresh() {
        // 1. 扫描包路径,加载所有带@Component注解的类
        scanPackage(basePackage);
        
        // 2. 实例化所有非懒加载的单例Bean
        for (String beanName : beanDefinitions.keySet()) {
            BeanDefinition bd = beanDefinitions.get(beanName);
            if (bd.isSingleton() && !bd.isLazyInit()) {
                getBean(beanName);
            }
        }
    }
    
    /**
     * 扫描包路径
     */
    private void scanPackage(String packageName) {
        String path = packageName.replace('.', '/');
        URL url = Thread.currentThread().getContextClassLoader().getResource(path);
        if (url == null) return;
        
        File dir = new File(url.getFile());
        for (File file : dir.listFiles()) {
            if (file.isDirectory()) {
                scanPackage(packageName + "." + file.getName());
            } else if (file.getName().endsWith(".class")) {
                String className = packageName + "." + file.getName().replace(".class", "");
                try {
                    Class<?> clazz = Class.forName(className);
                    if (clazz.isAnnotationPresent(Component.class)) {
                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.value().isEmpty() ? 
                            decapitalize(clazz.getSimpleName()) : component.value();
                        
                        BeanDefinition bd = new BeanDefinition();
                        bd.setBeanClass(clazz);
                        bd.setSingleton(true);
                        beanDefinitions.put(beanName, bd);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 获取Bean - 核心方法(支持循环依赖)
     */
    public Object getBean(String beanName) {
        // 1. 从一级缓存获取
        Object singleton = singletonObjects.get(beanName);
        if (singleton != null) {
            return singleton;
        }
        
        // 2. 检测循环依赖
        if (singletonsCurrentlyInCreation.contains(beanName)) {
            // 正在创建中,直接返回null(实际Spring会从二级缓存获取早期引用)
            return null;
        }
        
        // 3. 创建Bean
        BeanDefinition bd = beanDefinitions.get(beanName);
        if (bd == null) {
            throw new RuntimeException("Bean not found: " + beanName);
        }
        
        // 标记正在创建
        singletonsCurrentlyInCreation.add(beanName);
        
        try {
            // 3.1 实例化
            Object bean = bd.getBeanClass().getDeclaredConstructor().newInstance();
            
            // 3.2 提前暴露(解决循环依赖)
            singletonObjects.put(beanName, bean);
            
            // 3.3 依赖注入
            injectDependencies(bean);
            
            // 3.4 初始化(执行@PostConstruct等)
            initializeBean(bean, beanName);
            
            // 移除正在创建标记
            singletonsCurrentlyInCreation.remove(beanName);
            
            return bean;
        } catch (Exception e) {
            throw new RuntimeException("Failed to create bean: " + beanName, e);
        }
    }
    
    /**
     * 依赖注入 - 通过反射注入@Autowired字段
     */
    private void injectDependencies(Object bean) throws Exception {
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                String fieldName = field.getName();
                Object dependency = getBean(fieldName);
                if (dependency == null) {
                    // 尝试按类型注入
                    dependency = getBeanByType(field.getType());
                }
                field.set(bean, dependency);
            }
        }
    }
    
    private Object getBeanByType(Class<?> type) {
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitions.entrySet()) {
            if (type.isAssignableFrom(entry.getValue().getBeanClass())) {
                return getBean(entry.getKey());
            }
        }
        return null;
    }
    
    private void initializeBean(Object bean, String beanName) throws Exception {
        // 执行初始化方法
        Method[] methods = bean.getClass().getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(PostConstruct.class)) {
                method.setAccessible(true);
                method.invoke(bean);
            }
        }
    }
    
    /**
     * Bean定义 - 简化版
     */
    public static class BeanDefinition {
        private Class<?> beanClass;
        private boolean singleton = true;
        private boolean lazyInit = false;
        // getter/setter...
    }
}

4.2 手写简易AOP框架

AOP的底层实现完全依赖BeanPostProcessor机制。通过实现BeanPostProcessor,可以在Bean初始化前后进行拦截处理。

代码语言:javascript
复制
/**
 * Bean后置处理器接口
 */
public interface BeanPostProcessor {
    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }
    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

/**
 * 自定义切面注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
}

/**
 * 通知类型注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Around {
    String value() default "";
}

/**
 * AOP后置处理器 - 核心实现
 */
public class AspectBeanPostProcessor implements BeanPostProcessor {
    
    private List<AspectInfo> aspects = new ArrayList<>();
    
    public AspectBeanPostProcessor(String basePackage) {
        // 扫描所有带@Aspect注解的类
        scanAspects(basePackage);
    }
    
    private void scanAspects(String packageName) {
        // 包扫描逻辑,找到所有@Aspect类
        // 解析@Around等注解,封装为AspectInfo
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 判断是否需要生成代理
        for (AspectInfo aspect : aspects) {
            if (aspect.match(bean.getClass())) {
                return createProxy(bean, aspect);
            }
        }
        return bean;
    }
    
    /**
     * 创建代理对象
     */
    private Object createProxy(Object target, AspectInfo aspect) {
        Class<?> targetClass = target.getClass();
        
        // 判断使用JDK代理还是CGLIB
        if (targetClass.getInterfaces().length > 0) {
            return Proxy.newProxyInstance(
                targetClass.getClassLoader(),
                targetClass.getInterfaces(),
                new AspectInvocationHandler(target, aspect)
            );
        } else {
            // CGLIB代理(使用Enhancer)
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(targetClass);
            enhancer.setCallback(new AspectMethodInterceptor(target, aspect));
            return enhancer.create();
        }
    }
    
    /**
     * JDK动态代理处理器
     */
    private static class AspectInvocationHandler implements InvocationHandler {
        private Object target;
        private AspectInfo aspect;
        
        public AspectInvocationHandler(Object target, AspectInfo aspect) {
            this.target = target;
            this.aspect = aspect;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 检查是否需要拦截
            if (!aspect.matchMethod(method)) {
                return method.invoke(target, args);
            }
            
            // 执行前置通知
            aspect.before(method, args);
            
            try {
                // 执行目标方法
                Object result = method.invoke(target, args);
                // 执行后置通知
                aspect.after(method, args, result);
                return result;
            } catch (Exception e) {
                // 执行异常通知
                aspect.afterThrowing(method, args, e);
                throw e;
            }
        }
    }
    
    /**
     * 切面信息封装
     */
    private static class AspectInfo {
        private Class<?> aspectClass;
        private Object aspectInstance;
        private String pointcut;
        private Method aroundMethod;
        
        public boolean match(Class<?> targetClass) {
            // 使用正则或AspectJ表达式匹配
            // 简化实现:检查类名是否包含特定模式
            return targetClass.getName().contains(pointcut.replace("*", ""));
        }
        
        public boolean matchMethod(Method method) {
            // 简化的方法匹配
            return true;
        }
        
        public void before(Method method, Object[] args) {
            // 执行@Before逻辑
        }
        
        public void after(Method method, Object[] args, Object result) {
            // 执行@After逻辑
        }
        
        public void afterThrowing(Method method, Object[] args, Exception e) {
            // 执行@AfterThrowing逻辑
        }
    }
}

将AspectBeanPostProcessor注册到容器后,每个Bean在初始化完成后都会经过postProcessAfterInitialization方法检查,如果需要AOP增强则返回代理对象,否则返回原对象。

五、总结

通过源码解析到手写实现,我们可以清晰地看到Spring框架的设计精髓:

  1. BeanDefinition抽象:将配置元数据与实例化逻辑分离,支持多种配置方式
  2. 三级缓存机制:用空间换时间,巧妙解决循环依赖问题
  3. BeanPostProcessor扩展点:提供灵活的AOP等增强能力
  4. 动态代理:根据目标类特征智能选择JDK代理或CGLIB代理

掌握这些核心原理后,再看Spring源码时会产生“庖丁解牛”般的快感。当遇到@Transactional失效、循环依赖报错等问题时,不再是盲目搜索,而是能快速定位问题根源。这正是一个Java高手从“会用”到“懂原理”的质变。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 从Spring源码解析到手写核心组件:深入IoC容器与AOP实现内幕
    • 一、为什么必须深入Spring源码?
    • 二、Spring IoC容器源码深度解析
      • 2.1 BeanDefinition:一切Bean的起点
      • 2.2 容器启动六步流程
      • 2.3 三级缓存:循环依赖的破解之道
    • 三、Spring AOP实现机制剖析
      • 3.1 代理模式的选择逻辑
      • 3.2 核心源码解析
    • 四、手写实现Spring核心组件
      • 4.1 手写简易IoC容器
      • 4.2 手写简易AOP框架
    • 五、总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档