Spring 源码笔记

也不指望有人看... 不过如果你看了的话, 希望你能告诉我你的感受, 以及可以改进的地方!

Spring源码分析

关键类介绍

ApplicationContext

万能的 applicationContext, 但实际上各种能力都是依赖于其他的类, 比如 getBean 是 beanFactory 的, publishEvent 是事件广播器的, 等等. 其本身是一个综合体, 整合这些能力, 便于开发者调用和理解.

# 下面列一下相关的接口, 抽象类, 和具体类
ApplicationContext
    是一个只读的 bean 容器
    可以加载解析配置文件(如xml)
    可以发布事件和注册监听
    具有国际化消息处理能力
ConfigurableApplicationContext
    是一个具有可配置能力的 容器(可设置各个参数, 如id, 父容器)
    具有容器生命周期概念, 如启动,停止,关闭.
AbstractApplicationContext
    模板方法模式的抽象类, 定义了容器的模板(refresh方法), 但由具体的子类实现部分方法
    管理Bean和BeanFactory的PostProcessor
    管理事件的监听和处理
AbstractRefreshableApplicationContext
    为可重复刷新的容器提供基类
    加入了BeanFactory的管理(创建/关闭等)
AbstractRefreshableConfigApplicationContext
    加入了configLocation字段, 用于某些容器初始化BeanFactory和Bean
AbstractXmlApplicationContext
    定义了读取xml配置文件来加载BeanFactory的代码, 使得子类只需提供配置文件地址或Resource
ClassPathXmlApplicationContext
    继承基类, 提供配置文件地址的构造方法, 调用refresh加载BeanFactory
        

BeanFactory

1.核心中的核心, 加载和管理 beanDefinitions(Bean配置信息), 创建和管理 bean 对象实例, 注册和管理 BeanPostProcessor(Bean扩展)

# 下面列一下相关的接口, 抽象类, 和具体类
BeanFactory
  定义了 Bean 的基础操作接口, 如 getBean, getType, isSingleton 等

SingletonBeanRegistry
  定义了单例对象的操作接口 (注册/获取/是否已存在) 

HierarchicalBeanFactory
  定义了父 BeanFactory 的相关操作接口(获取)

ConfigurableBeanFactory
  定义了对 BeanFactory 做各种配置的操作接口, 包括 BeanPostProcessor, setParentBeanFactory, destroyBean, registerAlias, resolveAliases 等

DefaultSingletonBeanRegistry
  实现了 SingletonBeanRegistry 接口, 即实现了单例对象的缓存管理, 包括一级/二级/三级(二级三级只依赖循环用上的两个缓存)
  
FactoryBeanRegistrySupport
  继承了 DefaultSingletonBeanRegistry
    实现对使用 FactoryBean 存储和获取 bean 对象实例方式的支持
    
AbstractBeanFactory
  继承了 FactoryBeanRegistrySupport
  实现了 BeanFactory/HierarchicalBeanFactory/ConfigurableBeanFactory 定义的接口
  实现了具体 getBean, 包括缓存管理等
  
AutowireCapableBeanFactory
  定义了根据 class 类型获取 BeanDefinition 信息以及 Bean 对象的接口

AbstractAutowireCapableBeanFactory
  继承自 AbstractBeanFactory 
  实现了 AutowireCapableBeanFactory 中定义的方法(就是实现了根据 class 获取 bean 或 BeanDefinition)
  实现了 createBean, 也就是真正的实例化一个对象的过程, 包括实例化, 为需要赋值的字段注入相应的值
  同时触发了 BeanPostProcessor 的方法调用
  
BeanDefinitionRegistry
  定义了 BeanDefinition 的注册/获取/移除
  
ListableBeanFactory
    定义了 BeanDefinition 的可遍历性
  
ConfigurableListableBeanFactory
  结合 ListableBeanFactory 和 ConfigurableBeanFactory 并补充完善了几个相关接口 (如 getBeanNamesIterator 接口 )

DefaultListableBeanFactory
  继承了 AbstractAutowireCapableBeanFactory
  实现了 BeanDefinitionRegistry/ConfigurableListableBeanFactory 的接口
 
# 总结:
定义处:
BeanFactory(getBean)
SingletonBeanRegistry(addSingleton)
HierarchicalBeanFactory(getParentBeanFactory)
ConfigurableBeanFactory(addBeanPostProcessor)
AutowireCapableBeanFactory(autowireBean)
BeanDefinitionRegistry(registerBeanDefinition)
ListableBeanFactory(getBeanDefinitionNames)
ConfigurableListableBeanFactory(getBeanNamesIterator)

实现处:
DefaultSingletonBeanRegistry(registerSingleton)
FactoryBeanRegistrySupport(getObjectFromFactoryBean)
AbstractBeanFactory(doGetBean)
AbstractAutowireCapableBeanFactory(createBean)
DefaultListableBeanFactory(registerBeanDefinition)

容器初始化过程

1.setParent(): 处理父容器 
2.setConfigLocations(): 解析并设置xml配置文件路径
3.refresh(): 创建 beanFactory 对象并初始化, 读取 xml 配置文件得到 beanDefinitions, 接着处理两种 PostProcessor, 然后添加国际化处理器和事件广播器以及相应的初始化和一些处理, 最后实例化单例的 bean 等等.

#外圈结束, 再看 refresh() 里面的每个方法
1.prepareRefresh(): 准备工作, 一些字段值的设置和处理.
2.obtainFreshBeanFactory(): 创建一个 beanFactory 对象并注册到 applicationContext (即赋值到字段上), 然后解析 xml 配置文件(或注解配置)的信息, 解析得到 beanDefinitions 并注册到容器中.
3.然后是一些对 beanFactory 对象的完善配置的代码
4.扫描并执行 BeanFactoryPostProcessor(其作用是为beanFactory对象添加东西提供扩展性), 其中我认识的就只有 ConfigurationClassPostProcessor(这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan等基础注解).
5.扫描实现了 BeanPostProcessor 接口的 bean 并注册到 beanFactory 中存起来, 等 createBean 创建对象时会在对应的时机执行一些对应的方法(钩子). 常见的各种 XxxAware 就是靠这个实现的咯.
6.接着, 初始化国际化资源处理器, 事件广播器, 并注册一些需要注册的事件(也注册容器内实现对应接口的 bean)
7.处理一些 beanFactory 的配置, 接着为所有单例且非懒加载的(不就是默认策略嘛) bean 创建实例, 缓存起来.
8.广播容器加载完成了的事件. 以及处理生命周期.

最后总结下, 先创建容器, 再将根据配置文件解析得到 BeanDefinition 注册到容器中, 然后处理两大扩展(BeanFactoryPostProcessor/BeanPostProcessor), 接着是Spring的国际化, 以及相当有用的事件广播器, 最后实例化 bean. 整体感觉其实很简单, 但其实有大量的工作交给了 BeanPostProcessor.

超长源码分析过程

// 先随便写个 main 方法, 如我写的, 可测试依赖循环问题和事件监听:
// 包名: cn.gudqs7.spring.tests, 改动则需同步修改xml哦
// 进入对应类代码: 快捷键 Cmd+Option+鼠标点击 (或 Ctrl+Alt+鼠标左键 ); 如果是接口松开 Option(或Alt)键

Test.java
public class Test {

    public static void main(String[] args) {
        ApplicationContext xmlContext = new ClassPathXmlApplicationContext("application-wq.xml");
        UserServiceImpl userService = xmlContext.getBean(UserServiceImpl.class);
        userService.sayHi();
    }

}


application-wq.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">

    <bean name="userService" class="cn.gudqs7.spring.tests.UserServiceImpl">
        <property name="starter"><ref bean="serverStarter"/></property>
    </bean>
    <bean name="serverStarter" class="cn.gudqs7.spring.tests.ServerStarter">
        <property name="userService"><ref bean="userService"/></property>
    </bean>

</beans>

    
UserServiceImpl.java
@Service
public class UserServiceImpl {

    @Resource
    private ServerStarter starter;

    public void sayHi() {
        System.out.println(starter);
        System.out.println("Hello Spring!");
    }

    public void setStarter(ServerStarter starter) {
        this.starter = starter;
    }
}


ServerStarter.java
@Service
public class ServerStarter implements ApplicationListener<ContextRefreshedEvent> {

    @Inject
    private UserServiceImpl userService;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        String applicationName = event.getApplicationContext().getApplicationName();
        System.out.println(applicationName);
        System.out.println(userService);
        System.out.println("========== started by gudqs7 ==============");
        System.out.println("========== started by gudqs7 ==============");
        System.out.println("========== started by gudqs7 ==============");
    }

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }
}

😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄

// 接下来, 进入ClassPathXmlApplicationContext#ClassPathXmlApplicationContext(java.lang.String) 方法中

// 其跳转到了
  public ClassPathXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {

        // 为容器的 parent 字段赋值, 若 parent 不为空, 且有 ConfigurableEnvironment, 则合并数据(将父容器有的加到子容器中)
        // 即执行了 org.springframework.context.support.AbstractApplicationContext.setParent()
        super(parent);

        // 为 configLocations 字段赋值(告知配置文件位置), 赋值前会根据环境变量解析(此时环境变量中只有系统环境变量: 如JAVA_HOME).
        setConfigLocations(configLocations);
        if (refresh) {
            // 注释在下面
      refresh();
        }
    }
  
  

😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄

// 然后具体的看 refresh 方法
public void refresh() throws BeansException, IllegalStateException {
        // 1.设置容器初始的一些属性(时间,状态),初始化占位符数据源并校验所有 bean 所使用的占位符是否存在, 清空事件和监听
        // 2.清空重置旧的 beanFactory, 再创建新的 beanFactory 并通过解析 xml或注解 加载 beanDefinitions
        // 3.设置了一些 beanFactory 的属性, 添加了几个有用的 BeanPostProcessor, 还添加了几个 bean 到容器中(都是环境相关的 bean)
        // 4.子类对beanFactory 添加自己的特殊的 BeanPostProcessor (如servletContxt/servletConfig注入)
        // 5.扫描容器中实现了 BeanFactoryPostProcessor 接口的 bean 将其注册到 beanFactory 中并执行
        // 6.扫描容器中实现了 BeanPostProcessor 接口的 bean 将其注册到 beanFactory 但不执行(实例化 bean 对象那会有几个执行时机)
        // 7.创建一个国际化资源解析器并注册到 beanFactory; 创建一个事件广播器并注册到 beanFactory.
        // 8.调用子类的其他刷新时需要做的事情(模板方法)
        // 9.扫描容器中实现了 ApplicationListener 接口的 bean, 将其预存到广播器中但不执行
        //10.完成 beanFactory 的一些配置(包括终结一些东西, 如 setTempClassLoader(null) ); 将单例的 bean 创建出来放入容器中(未设置lazy-init=true)的 bean
        //11.广播 ContextRefreshedEvent 事件, 初始化LifeCycleProcessor及调用其 onRefresh 方法.

        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            // 设置容器初始的一些属性(时间,状态),初始化占位符数据源并校验所有 bean 所使用的占位符是否存在, 清空事件和监听
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            // 清空重置旧的 beanFactory, 再创建新的 beanFactory 并解析 xml或注解 加载 beanDefinitions
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // 设置了一些 beanFactory 的属性, 添加了几个有用的 BeanPostProcessor, 还添加了几个 bean 到容器中(都是环境相关的 bean)
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 子类对beanFactory 添加自己的特殊的 BeanPostProcessor (如servletContxt/servletConfig注入)
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                // 扫描容器中实现了 BeanFactoryPostProcessor 接口的 bean 将其注册到 beanFactory 中并执行
                //   扫描6次, 2(BeanDefinitionRegistry/BeanFactory) x 3(优先级:高/中/其他)
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 扫描容器中实现了 BeanPostProcessor 接口的 bean 将其注册到 beanFactory 但不执行; 扫描6次: 2(MergedBeanDefinitionPostProcessor/其他) x 3(优先级: 高/中/其他)
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                // 创建一个国际化资源解析器并注册到 beanFactory.
                initMessageSource();

                // Initialize event multicaster for this context.
                // 创建一个事件广播器并注册到 beanFactory.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                // 调用子类的其他刷新时需要做的事情(模板方法)
                onRefresh();

                // Check for listener beans and register them.
                // 将可能存在的 applicationListeners 注册到事件广播器中(新建时是不存在的),
                // 然后扫描容器中实现了 ApplicationListener 接口的 bean, 将其预存到广播器中但不执行
                // 将之前 publishEvent() 想广播的事件广播出去, 然后字段 earlyApplicationEvents 赋值为空(代表之后可立即广播)
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                // 完成 beanFactory 的一些配置(包括终结一些东西, 如 setTempClassLoader(null) )
                // 注册默认的表达式解析器(若无相应的bean存在)
                // 扫描容器中实现了 LoadTimeWeaverAware 接口的 bean, 并触发(getBean)之前注册过的 BeanPostProcessor
                // 将单例的 bean 创建出来放入容器中(未设置lazy-init=true)的 bean
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                // 广播 ContextRefreshedEvent 事件, 初始化LifeCycleProcessor及调用其 onRefresh 方法.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                // 销毁缓存的单例对象
                destroyBeans();

                // Reset 'active' flag.
                // 变更状态
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                // 清空公共工具产生的缓存(内存松一口气).
                resetCommonCaches();
            }
        }
    }

我错了, 代码都放上去不如给个GitHub地址, 接下来省略代码吧, 只放注释😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄

// 挨个看里面的方法
org.springframework.context.support.AbstractApplicationContext#prepareRefresh
    // 1.设置容器初始的一些属性, 如启动时间, 当前状态
        // 2.打印开始日志
        // 3.初始化占位符数据源
        // 4.校验所有 bean 所使用的占位符是否存在
        // 5.清空事件和监听
        // Switch to active.
  
org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
    // 1.存在旧的则先摧毁 bean 对象实例及缓存数据, 再将旧的置为 null
        // 2.创建一个新的 beanFactory 对象, 再设置 id及一些配置
        // 3.扫描并加载 beanDefinations
        // 4.设置这个新的 beanFactory 对象为 applicationContext 的 beanFactory 字段值.
  
org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
    // 1.设置 beanFactory 的类加载器
        // 2.设置 beanFactory 的表达式解析器
        // 3.1:注册一个 BeanPostProcessor 用于将实现了ApplicationContext能力相关的Aware接口的 bean, 触发赋值setter 注入 applicationContext 对象
        // 3.2:设置 beanFactory 处理 bean 时要忽略的接口(主要是setter注入时忽视一些也是setter的方法, 因为这些方法会由 PostProcessor 来触发)
        // 4.注册一些特殊的 bean(注入这些bean时会注入 this 对象: 多功能工具人 ApplicationContext, 可见其和普通 bean 的注册方式不一样)
        // 5.注册一个 BeanPostProcessor 用于检测加载的 bean 是否实现了 ApplicationListener 接口, 若是, 则注册到事件广播器中(不是,是暂存在applicationListeners字段中, 等事件广播器创建后才注册)
        // 6.注册一个 BeanPostProcessor 用于触发实现了 LoadTimeWeaverAware 接口的 bean 的 setLoadTimeWeaver() 社会 LTW 实例.
        // 7.注册几个环境相关 bean 到容器中(Spring的环境对象, 以及系统环境变量和系统配置文件)

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
    // 1.若 beanFactory 实现了 BeanDefinitionRegistry 接口(new AnnotationConfigApplicationContext 就实现了)
        //    则扫描所有实现了 BeanDefinitionRegistryPostProcessor 接口的 bean, 根据优先级分三类(高/中/其他)依次执行
        // 2.然后扫描所有实现了 BeanFactoryPostProcessor 接口的 bean, 依旧是根据优先级分三类依次执行.
        // 3.每次执行前都会根据 Order 信息排序, 再遍历执行
  
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)
    // 1.扫描6次: 2(MergedBeanDefinitionPostProcessor/其他) x 3(优先级: 高/中/其他)
        //    将其加入到 beanFactory 的 beanPostProcessors 集合中
        // 2.再次加入 ApplicationListenerDetector (用于处理实现 ApplicationListener 的 bean 注册到事件广播器), 主要是使其在链末尾, 可以最后执行.

org.springframework.context.support.AbstractApplicationContext#registerListeners
    // 1.将可能存在的 applicationListeners 注册到事件广播器中(新建时是不存在的)
        // 2.扫描容器中实现了 ApplicationListener 接口的 bean, 将其预存到广播器中但不执行
        // 3.将之前 publishEvent() 想广播的事件广播出去, 然后字段 earlyApplicationEvents 赋值为空
        //    (因为 publishEvent() 中根据是否为空判断立刻执行或先存着) (另这也解释了 prepareRefresh() 中为何要赋值一个空集合)

  
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
    // 1.完成 beanFactory 的一些配置
        // 2.注册默认的表达式解析器(若无相应的bean存在)
        // 3.扫描容器中实现了 LoadTimeWeaverAware 接口的 bean, 并触发(getBean)之前注册过的 BeanPostProcessor
        // 4.将单例的 bean 创建出来放入容器中(未设置lazy-init=true)的 bean

org.springframework.context.support.AbstractApplicationContext#finishRefresh
    // 1.清空资源缓存
        // 2.创建一个生命周期管理器(start, refresh, stop等)并注册到 beanFactory
        // 3.触发生命周期管理器的 onRefresh()
        // 4.广播容器刷新完成的事件
        // 5.为 Spring Tool Suite 提供某些便捷(没用过, 不知道...)

可算复制完了, 如果你有幸直接跳读到这里, 那么送上地址 : 注意分支吧

另外上面方法前带个 # 的, 复制到 IDEA 双击 Shift 然后粘贴, 选择 Symbols 搜索更准确呢!

获取容器对象过程

# 从getBean(Class type) 中进入
1.检查 applicationContext 和 beanFactory 的状态, 若有异常则给出准确的错误.
2.扫描容器中所有此 type 的 beanName, 遍历判断每个 beanName 是否可用
   可用则判断可用的个数是否刚好是一个, 是则直接调用 getBean() 返回对象实例
   若可用的个数超过一个, 则根据 beanDefinition 的 isPrimary 和对比配置的优先级是否为有最高的再返回最高的
   若都不行, 则报错.
3.接着看 getBean, 先试着从单例的缓存中获取, 若存在则返回.
4.若缓存中不存在, 则判断父容器是否存, 若存在则从父容器获取
   若父容器不存在, 则自己新建, 先标记 beanName 到 alreadyCreated 中(表示已经创建了防止重复创建) 再开始创建一个 bean.
5.创建一个新的 bean 实例, 先处理 beanDefinition 的 dependsOn 属性(即若存在则先调用 getBean 获取依赖的 bean)
6.若 beanDefinition 的设置是单例, 则通过闭包对创建对象前后进行一些异常处理和缓存处理(主要是彻底创建完后加入到单例一级缓存, 移除二级和三级缓存[循环依赖相关的两个缓存]).
7.通过反射根据 beanClass 创建一个对象实例, 然后将其添加到 singletonFactories 中(解决依赖循环问题)
8.调用 populateBean() 为对象的字段(属性)注入它所需要的值(可能是@Resource, @Value等); (此时可能会遇到依赖循环问题, 但解决这个问题的缓存在此之前就添加了, 所以不怕)
9.最后调用 initializeBean() 完成 bean 的初始化(调用 bean 的一些方法, 如 afterPropertiesSet), 返回对象实例.

总结: 先根据 type 找到 beanName, 找到后根据 beanName 创建对象; 创建对象前先检查缓存(单例), 再考虑父容器, 最后才是自己创建, 自己创建会先创建 dependsOn 的 bean 对象, 然后才通过反射实例化出一个对象实例(这里反射用到的class和构造方法, 通过实现 SmartInstantiationAwareBeanPostProcessor接口都可进行干预), 实例化后存到二级缓存, 再为字段赋值(注入); 最后调用 bean 的 init 相关的接口(如afterPropertiesSet), 就可以返回这个对象实例了.

超长源码分析过程

// 从这个方法进入
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
  // 判断容器的状态, 确保 beanFactory 可用.(主要是若不可用, 提示的错误信息会比getBeanFacgtory()中更准确)
  // 使用 beanFactory 的 getBean 方法获取对象并返回.
  assertBeanFactoryActive();
  return getBeanFactory().getBean(requiredType);
}

// 然后其他所有涉及的核心方法的注释
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean
    // 调用 resolveNamedBean, 如存在 bean 则直接返回. (核心)
        // 若不存在则从父容器中寻找, 父容器实现了 DefaultListableBeanFactory 则调与同子容器相同的方法
        // 若没实现则 通过 getBeanProvider 获取.
  
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)
    // 1.调用 getBeanNamesForType 获取所有与 type 相匹配的 beanName 集合.
        // 2.遍历判断每个 beanName 是否可用
        // 3.若可用的 beanName 只有一个, 则调用 getBean(beanName) 获取对象实例并返回
        //   若可用数超过一个, 则试着根据是否主要以及高优先级来确定一个 beanName 实例, 若能确定则返回, 不能则报错.

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
    // 1.获取完整的 beanName
        // 2.调用 getSingleton1() 检查是否存在缓存, 这层检查可防止依赖循环.
        //     若存在, 则通过 getObjectForBeanInstance() 判断缓存的是 bean 还是 FactoryBean 并返回相应的对象实例.
        // 3.若不存在, 先试着从父容器获取(子容器不存在这个 beanDefinition 且父容器不为空)
        //     没有父容器则 调用 markBeanAsCreated() 标记这个 bean已经创建了 (先标记, 再创建)
        //     获取 beanDefinition, 判断其 dependsOn 属性是否存在, 存在则 先获取依赖的 bean
        //     调用 getSingleton2() 处理单例缓存
        // 4.而 getSingleton2() 中的闭包中 执行的 createBean() 方法中则才是创建实例并调用 BeanPostProcessor

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
    // 1.判断是否存在于 singletonObjects 中
        // 2.若不存在则判断 bean 是否处于创建中(未创建完成, 如循环依赖时)
        // 3.若处于创建中, 则同步后判断是否存在于 earlySingletonObjects (也就是 singletonFactories 移除后存入的地方)
        //      (因为FactoryBean占用空间大, 获取对象麻烦且速度更慢, 这是为了防止如果循环依赖链条很长 多次获取浪费CPU的问题)
        // 4.不存于 earlySingletonObjects 则代表第一次(也只会有一次)取 singletonFactories
        //    取出后调用 getObject() 并将其存入到 earlySingletonObjects, 然后从 singletonFactories 中移除. 以后就少走几行代码了.
  
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
    // 1.先确保是第一次创建单例对象, 防止重复创建
        // 2.进行一些异常处理
        // 3.调用 singletonFactory.getObject() 创建对象
        // 4.创建对象结束添加单例缓存和清空 singletonFactories / earlySingletonObjects 缓存.
  
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
    // 1.调用 resolveBeanClass 解析得到真正的 bean class, 若解析不为空且处于某些情况下, 则复制一份 beanDefinition 并设置 beanClass 为解析所得
        // 2.执行 BeanPostProcessor 的 postProcessorsBeforeInstantiation() 方法
        // 3.调用 doCreateBean() 创建对象 并返回

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
    // 1.调用 createBeanInstance() 获得一个 对象实例的 包装类
        // 2.同步锁下执行 BeanFactoryPostProcessor 的 postProcessMergedBeanDefinition().
        // 3.添加 singletonFactories 缓存, 移除 earlySingletonObjects; 解决循环依赖问题.
        // 4.调用 populateBean() 检查字段是否需要注入对象实例, 是则获取对应的 bean 注入. (可能引起循环依赖)
        // 5.调用 initializeBean() 执行对象的一些 Aware 和 init 方法和 BeanPostProcessor 的 postProcessBeforeInitialization.
        // 6.最后返回对象实例.


各种实现的原理

1.为何我写的 class 实现一些接口(如ApplicationContextAware)后并放入容器中, 就可以获取到一些对象(如applicationContext)?
2.为何我写的 class 实现 ApplicationListener<XxxEvent> 后并放入容器中, 就能监听我想知道的事件?
3.为何Spring中遇到各种顺序问题, 只需要实现 Ordered 接口(或加上@Order注解)就能使其有序?
4.Spring是如何解决循环依赖的(指用字段注入而非构造方法)?
5.Spring可以用注解替换XML配置文件了, 是如何实现的呢(常用注解的实现原理)?
6.Spring AOP是如何实现的(指@Aspect)?
7.Spring 事务是如何实现的(指@Transaction)?

为何我写的 class 实现一些接口(如ApplicationContextAware)后并放入容器中, 就可以获取到一些对象(如applicationContext)?

1) 首先 AbstractApplicationContext#prepareBeanFactory 会添加一个ApplicationContextAwareProcessor
2) 这个 beanPostProcessor 负责在bean初始化之前注入context对象.
3) 这个 beanPostProcessor 的执行时机是在 doCreateBean 中的 postProcessBeforeInitialization()

为何我写的 class 实现 ApplicationListener<XxxEvent> 后并放入容器中, 就能监听我想知道的事件?

1) 在 AbstractApplicationContext#registerListeners() 中扫描容器内所有相关实现类加入到事件监听者集合中
2) 然后在publishEvent时,遍历事件监听者集合调用bean的方法即可。观察者模式!
3) 另外也用了BeanPostProcessor去实现, 叫 ApplicationListenerDetector, 加入时机同1, 执行时机同1.
4) 至于为何使用2种机制, 应该是因为 registerListeners() 时, 扫描只是当前的, 后续可能容器内的 bean 还会增加(我也猜不到啥形式增加, 反正简单写个类肯定不会), 所以还是需要 ApplicationListenerDetector 在这个 Bean 初始化时加入到监听者中去.

为何Spring中遇到各种顺序问题, 只需要实现 Ordered 接口(或加上@Order注解)就能使其有序?

因为 Spring 预先在执行这些东西之前, 进行一个排序动作, 然后才遍历执行. 包括AOP, BeanFactoryPostProcessor, BeanPostProcessor .

1) 比如说 BeanPostProcesser, 容器扫描后, 会像对bean集合排序, 再遍历执行.
2) 详细过程见 PostProcessorRegistrationDelegate#sortPostProcessors()

Spring是如何解决循环依赖的(指用字段注入而非构造方法)?

1) 首先, 假定有两个单例 bean A 和 B, A 持有 B, B 持有A, 构成循环
2) 此时程序调用getBean获取A,则在 doCreateBean 中 创建后将 bean 缓存到 singletonFactories 中
3) 然后设置属性B, 解析属性, 需要获取B对象
4) 获取B, 则执行doCreateBean 后执行解析属性, 需要获取 A对象 (又一次)
5) 获取A, 进入 doGetBean 中的 getSingleton, 此时判断 singletonFactories 中有A, 则可以直接取出A
6) 获得A后, 即可完成B的属性赋值, 然后会完成B的创建.
7) B创建完后, A就能获得B, 则A也完成了属性赋值, 最后完成创建A.
8) 到此, 返回即可.

> 总结: 首次获取A, 创建A对象后缓存一个存储A对象的 ObjectFactory 实例, 再解析属性时触发 getBean(B), 同理也会做缓存, 然后也解析属性, 触发getBean(A), 第二次获取A, 进入另一个逻辑, 返回 ObjectFactory 实例中存储的对象A, 即可完成getBean(A), 然后完成getBean(B), 再完成外层的getBean(A).  
  
TIPS:
步骤4中, 会先判断 earlySingletonObjects, 不存在才判断 singletonFactories, 而从 singletonFactories 中取得对象后, 则会将其从 singletonFactories 移除并加入 earlySingletonObjects

这是因为 singletonFactories 缓存的 FactoryBean, 若反复调用 getObject(), 则每次获取都会调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference 方法, 而此方法会执行 SmartInstantiationAwareBeanPostProcessor 的 getEarlyBeanReference(), 这会导致 BeanPostProcessor 重复执行, 显然是不行的.

Spring可以用注解替换XML配置文件了, 是如何实现的呢(常用注解的实现原理)?

1) 首先是指定包名或指定类名
    如指定包名则 scan 时会执行, 如指定类名则在构造方法初始化 reader 时执行
2) 无论哪种, 最终都会走一段代码 AnnotationConfigUtils#registerAnnotationConfigProcessors()
3) 这段代码会添加一些 BeanFactoryPostProcessor
    如 ConfigurationClassPostProcessor 负责解析 @Configuration/@Import/@Bean 等注解
        然后由 ConfigurationClassBeanDefinitionReader 负责将信息转换成BeanDefinition再注册到容器。
    如 AutowiredAnnotationBeanPostProcessor 负责解析 @Autowired/@Value 注解
    如 CommonAnnotationBeanPostProcessor 负责解析 @Resource 注解
    解析放在 postProcessProperties() 方法中, 先扫描bean的字段和方法, 然后一一调用方法和为字段注入值
4) 之后, 他会将扫描的类放到 beanDefinitions 中(或指定的类注册进去)
5) BeanFactory加载完毕后, 回到AbstractApplicationContext的refresh逻辑
    如会执行 postProcessBeanFactory(), 调用前面加入的ConfigurationClassPostProcessor
    然后会添加更多的类到容器中.
    
注意事项:
    @Configuration 和 @Component的区别?
    观察发现,即使使用@Component 其下带 @Bean 的方法依然可以注入到容器中。所以似乎两者没有区别?
    仔细查看源码和资料后,发现 postProcessBeanFactory() 方法在 processConfigBeanDefinitions() 后还会调用 enhanceConfigurationClasses()
    而在这个方法中, 对前面解析了class 是 CONFIGURATION_CLASS_FULL (即代表@Configuration)的类
    会生成一个 cglib 的代理, 这样获取@Bean注解的方法的bean时,不会每次调用方法new 一个, 而是有缓存.

总结: 就是利用 BeanFactoryPostProcessor 可获取 BeanDefinitionRegistry 对象, 然后扫描容器内带有注解的 bean, 解析这些注解得到一些 BeanDefinition, 再通过获得的 BeanDefinitionRegistry对象注册到 BeanFactory 中.

Spring AOP是如何实现的(指@Aspect)?

1) 使用 @EnableAspectJAutoProxy
2) @EnableAspectJAutoProxy 中使用了 @Import(AspectJAutoProxyRegistrar.class)
3) ConfigurationClassPostProcessor 会解析@Import, 进入 registerBeanDefinitions() 中
4) registerBeanDefinitions() 中添加了 AnnotationAwareAspectJAutoProxyCreator 到容器中
5) AnnotationAwareAspectJAutoProxyCreator 本质上时一个 BeanPostProcessor
6) 因此在 createBean 时, 会被自动调用. 其中 postProcessAfterInitialization() 负责创建代理对象
7) 而 getAdvicesAndAdvisorsForBean() 则负责查找对应的增强. 然后会调用子类的findCandidateAdvisors
8) 如 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors() 负责注解编写增强@Before/@After等
9) 简单说下逻辑, 就是查找容器所有类, 判断这个类有没有 @Aspect 注解, 然后先找出所有Pointcut
    再遍历所有方法, 找出方法上带有@Before等注解且有关联的Pointcut的方法,
    然后使用这个方法和关联的Pointcut 来new 一个Advisor, 加入到Advisor集合中, 遍历结束后返回即可.
10) 查找到所有的增强后, 再比较Pointcut表达式是否匹配当前的bean, 如可以则加入.
11) 根据找到的Advisor集合, 创建一个带配置(advisor集合等)的代理对象, 代理对象执行方法前
12) 会先根据配置中的advisor集合生成一个执行链, 然后在拦截代理方法处调用. 执行链会负责执行通知.
13) 不同的通知由不同的适配器执行.

总结就是通过 @EnableAspectJAutoProxy 的@Import, 使得程序最终会执行 AnnotationAwareAspectJAutoProxyCreator 的 postProcessAfterInitialization(对象初始化后调用) 方法, 这个方法在 BeanFactory创建完对象后触发, 此时便可通过 CGlib 等动态代理技术为 创建的 bean 对象创建一个代理对象, 然后这个代理对象会根据 Pointcut 找到关联的 Advisor, 并在合适的时机执行对应的 Advisor, 如 @Before产生的Advisor 会在执行了 bean 对象的指定方法(看Pointcut配置)后执行.

Spring 事务是如何实现的(指@Transaction)?

0) 事务是由AOP实现的, 所以需要找到对应的Pointcut 和 Advisor
1) 打开了 @EnableTransactionManagement 注解
2) 然后@Import 了 TransactionManagementConfigurationSelector
3) 之后导入了 ProxyTransactionManagementConfiguration 到容器中
4) ProxyTransactionManagementConfiguration 带有 @Configuration
5) @Bean 注入了一个通用的Advisor: BeanFactoryTransactionAttributeSourceAdvisor
6) 这个Advisor的 Pointcut 是由 TransactionAttributeSourcePointcut 实现的
    实现逻辑是 TransactionAttributeSourcePointcut 的 matches()
    这个方法调用了 getTransactionAttributeSource() 获取 AnnotationTransactionAttributeSource
    然后通过 getTransactionAttribute() 调用了 findTransactionAttribute()
    最终使用SpringTransactionAnnotationParser 类判断方法是否有@Transactional注解
    并解析注解信息然后返回. 另外这个方法还可以获取@Transactional注解的信息, 而这里只用于判断是否需要拦截这个方法.
7) TransactionInterceptor 是一个Advisor
    也可以通过AnnotationTransactionAttributeSource获取@Transactional注解上的信息
    然后在invoke中, 拦截方法, 打开事务, 在执行完方法后, 提交事务, 报错时回滚事务
    这个 Advisor 不同于传统的前置/后置, 而是更具体的 MethodInterceptor(动态代理直接相关).

总结: 就是基于AOP实现的, 只需找到对应的 Pointcut 和 Advisor 即可. Pointcut 就是根据 @Transaction 注解判断方法是否需要代理, 这个很简单; 比较有意思的是 Advisor 不是我们写AOP那种 @Before,@Around之类的, 而是更接近动态代理原始的语法的 MethodInterceptor 即 TransactionInterceptor.

BeanFactoryPostProcessor 相关类分析

BeanFactoryPostProcessor 生效原理

生效原理就是, ApplicationContext 的 refresh 方法中会扫描出容器中实现了 BeanFactoryPostProcessor 接口的 bean, 将其排序后执行相应的接口, 这样我们写的类实现的相应的接口的方法就被执行了.

常用的 BeanFactoryPostProcessor
# ConfigurationClassPostProcessor
这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan 等基础注解. 是注解开发的基石, 更是 Spring Boot 的基石.

BeanPostProcessor 相关类分析

BeanPostProcessor 生效原理

在 refresh() 中会扫描容器中所有 实现了 BeanPostProcessor 接口的类, 添加到 BeanFactory 的 beanPostProcessors 字段中(是个List[CopyOnWriteArrayList自定义版, 自定义加入了清空缓存的逻辑]), 然后在 BeanFactory 创建对象时 createBean() 在适当的时机调用对应的方法.

有哪几种 BeanPostProcessor (默认的+扩展)
1.InstantiationAwareBeanPostProcessor
    postProcessAfterInstantiation: 对象实例化后调用
    postProcessBeforeInstantiation: 对象实例化前调用
    postProcessProperties: 设置属性值前
    postProcessPropertyValues: 设置属性值前, 若上个方法不处理(返回null)才会触发

2.SmartInstantiationAwareBeanPostProcessor
  predictBeanType: 获取一个 bean 的 class 类型前调用
  getEarlyBeanReference: 获取一个二级缓存对象(singletonFactories的getObject)时调用
  determineCandidateConstructors: 决定一个 bean 实例化的构造参数是什么时调用
    
3.DestructionAwareBeanPostProcessor
    postProcessBeforeDestruction: 对象销毁前调用
    requiresDestruction: 判断这个类针对某个 bean 是否执行 postProcessBeforeDestruction()
    
4.MergedBeanDefinitionPostProcessor
  postProcessMergedBeanDefinition: 在创建对象前调用, 可对 BeanDefinition 做修改
  resetBeanDefinition: 在重置 BeanDefinition 时调用, 用于清空 PostProcessor 对应的缓存
    
5.BeanPostProcessor(基础)
  postProcessBeforeInitialization: 创建对象后(也设置好了字段), 在调用 init 之前调用
  postProcessAfterInitialization: 在创建对象时, 调用了 init 之后调用
  
总结: 
0.对 BeanDefinition 做干预
1.对象实例化过程中(对class/构造参数进行干预)
2.对象实例化前后
3.对象设置属性前, 对属性做干预
4.对象初始化(init)前后
5.对象销毁前

调用时机

    // 1.1: InstantiationAwareBeanPostProcessor 的 postProcessAfterInstantiation()
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean 第一段
        // 1.2: InstantiationAwareBeanPostProcessor 的 postProcessProperties()
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean 第二段
        // 1.3: InstantiationAwareBeanPostProcessor 的 postProcessPropertyValues
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean 第三段
        // 1.4: InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation()
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation 中

        // 2.1: SmartInstantiationAwareBeanPostProcessor 的 predictBeanType()
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType 中
        // 2.2: SmartInstantiationAwareBeanPostProcessor 的 getEarlyBeanReference()
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getEarlyBeanReference 中
        // 2.3: SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors()
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors 中

        // 3.1: MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition()
        //   在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors 中
        // 3.2: MergedBeanDefinitionPostProcessor 的 resetBeanDefinition()
        //   在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resetBeanDefinition 中

        // 4.1: DestructionAwareBeanPostProcessor 的 postProcessBeforeDestruction()
        //   在 org.springframework.beans.factory.support.DisposableBeanAdapter.destroy 中
        // 4.2: DestructionAwareBeanPostProcessor 的 requiresDestruction()
        //   在 org.springframework.beans.factory.support.DisposableBeanAdapter.filterPostProcessors 和 org.springframework.beans.factory.support.DisposableBeanAdapter.hasApplicableProcessors 中


😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁

# 有哪些常用的 BeanPostProcessor
1.AsyncAnnotationBeanPostProcessor: 用于在将 @Async 相应的 Advisor 加入到对象的代理中
2.ScheduledAnnotationBeanPostProcessor: 用于处理 @Scheduled 注解, 将 bean 生产代理类
3.AnnotationAwareAspectJAutoProxyCreator: AOP 实现核心类
4.AutowiredAnnotationBeanPostProcessor: 用于处理 @Autowired 注解
5.ApplicationListenerDetector: 用于处理实现 ApplicationListener 接口的 bean 对象, 将其添加到事件广播器的监听者集合中.
...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,646评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,979评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,391评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,356评论 0 215
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,740评论 3 293
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,836评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,022评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,764评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,487评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,728评论 2 252
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,200评论 1 263
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,548评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,217评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,134评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,921评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,919评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,766评论 2 274

推荐阅读更多精彩内容