白话文剖析[spring4.2.1.RELEASE] IOC核心架构

来源:互联网 发布:淘宝不评价有信誉吗 编辑:程序博客网 时间:2024/05/01 05:29

在这篇文章中,我将用第一人称的方式向你阐述spring4.2.1.RELEASE IOC部分的基本架构,你可以用如下的简单demo开启源码debug之旅

demo包含三个文件


User.java

public class User {    @Override    public String toString() {        return "hi, I am a user!";    }}

user.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean class="ch0.User"/></beans>

UserTest.java

public class UserTest {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("ch0/user.xml");        User user = context.getBean(User.class);        System.out.println(user);    }}

UserTest.java 中通过ClassPathXmlApplicationContext 创建了一个上下文,xml文件在类路径下,然后通过getBean 的方式可以拿到该bean

我们直接进到new ClassPathXmlApplicationContext(“ch0/user.xml”); 看看我到底做了什么事情~_~

ClassPathXmlApplicationContext.java

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {        this(new String[] {configLocation}, true, null);}

调用

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)            throws BeansException {        // 层层调用父类构造函数, 最终只是为了获取ResourcePatternResolver, 我需要这玩意是因为我        // 要将你传给我的配置文件("ch0/user.xml")这个参数转换为我内部可以处理的资源抽象 Resource         super(parent);        // 你可以不用告诉我非常精确的配置文件, 可以写占位符。在这个函数里面,我可以解析出完整的配置文件路径        setConfigLocations(configLocations);        // 基本都需要刷新的啦(refresh == true),在刷新上下文的时候,我会用你给我的配置文件完成几乎所有的事情哦        if (refresh) {            refresh();        }}

上面的函数先调用super(parent) 层层往上调用,最终发现做了这么一件事情

AbstractApplicationContext.java

public AbstractApplicationContext() {        this.resourcePatternResolver = getResourcePatternResolver();}

resourcePatternResolver 这从字面上就可以知道这家伙是做资源解析的用的呢,查看一下ResourcePatternResolver 的定义,发现重点只有这么一行

ResourcePatternResolver.java

    Resource[] getResources(String locationPattern) throws IOException;

这里的 locationPattern 代表实际的资源路径(基本上就等同于xml文件路径啦),这家伙可以把一个资源路径转换为描述资源的抽象Resource, 好了,初次看spring源码了解到这里就够了,关于 Resource 的深入里面后面会后专题分析!

继续下面一行

setConfigLocations(configLocations);

public void setConfigLocations(String... locations) {        if (locations != null) {            Assert.noNullElements(locations, "Config locations must not be null");            this.configLocations = new String[locations.length];            for (int i = 0; i < locations.length; i++) {                this.configLocations[i] = resolvePath(locations[i]).trim();            }        }        else {            this.configLocations = null;        }}

这一句的作用就是将创建ApplicationContext传入进来的ch0/user.xml 转换为合法的location,将location里面类似${key} 的placeHolder 转换为实际的值

protected String resolvePath(String path) {        return getEnvironment().resolveRequiredPlaceholders(path);}

而转换过程中会通过getEnviroment()拿到ConfigurableEnvironment对象来进行占位符${}的替换,标准的Enviroment对象为

StandardEnvironment.java

public class StandardEnvironment extends AbstractEnvironment {    public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";    public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";    @Override    protected void customizePropertySources(MutablePropertySources propertySources) {        propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));        propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));    }}

可以看到在设置替换placeHolder的源的时候,最终会通过getProperties(),和System.getenv()来获取启动jvm的时候的环境变量和系统环境变量,也就是说,如果你传入的location里面有个${key} 占位,而jvm参数或者系统环境变量里面刚好有个变量叫做key 那么spring在解析该location的时候,会将该占位解析为对应的value


接下来,到了

if (refresh) {    refresh();}

这一行可是我的重头戏啊,我的核心功能都在这个refresh() 方法里面搞定哦
在我们这个demo中,refresh 参数为true,所以,直接进入到refresh()方法,激动人心的时刻终于到来,go!

AbstractApplicationContext.java

public void refresh() throws BeansException, IllegalStateException {        synchronized (this.startupShutdownMonitor) {            // 刷新工厂之前需要做一些准备工作的啦,就想你在运动之前要做一些准备运动一样哦             prepareRefresh();            // 我会告诉我的子类创造一个工厂,来把我需要创建bean的原料BeanDefinition准备好            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();            // 原料准备好之后呢,我要声明一些特殊的依赖关系, 所谓依赖,就是我在创造一个bean A的时候,发现它里面有另外一个属性B            // 那么B就是A的依赖,我在创造A的时候,必须先把B创造好,特殊关系的依赖就是指我遇到B的类型,我该放弃呢,还是告诉他直接用            // 现成的(也就是不用再去创造B了)            prepareBeanFactory(beanFactory);            try {                // 这里没啥,就是留给子类做扩展的啦                postProcessBeanFactory(beanFactory);                // 到了这里,工厂已经准备好了,如果你之前告诉过我工厂准备好之后应该干什么事情,这边我就可以满足你的需求哦                // 不信,你去看看BeanFactoryPostProcessors接口是干嘛用的吧==                invokeBeanFactoryPostProcessors(beanFactory);                // 在创建一个bean的前后,我也留给你很多扩展,原理上和上面的工厂扩展差不多的哦                registerBeanPostProcessors(beanFactory);                // 就是处理一些国际化的操作啦,啊?什么是国际化,就是i18n啦,还不懂?你没救了                initMessageSource();                // 我的功能很丰富,除了可以给你创建bean,还可以有事件管理的功能哦,这里我就创建一个管理器(ApplicationEventMulticaster(),                // 用来注册事件(ApplicationEvent)                // 我会将这些事件广播给合适的监听者(ApplicationListener)那边哦                initApplicationEventMulticaster();                // 啥也不干,留给子类扩展啦                onRefresh();                // 前面不是事件管理器搞好了嘛,这边呢,就是把那些事件监听器给注册进来啦,这样来一个新的事件我就知道该发给谁啦                registerListeners();                // 如果某些bean告我我,他想在我工厂创建之初就想初始化(一般要是单件singleton并且lazy-init为false),那么我在这个函数会满足他                finishBeanFactoryInitialization(beanFactory);                // 终于刷新完了,我要开始发布事件了!                finishRefresh();            }            // 什么?刷新的时候报错了?oh my god,我需要做一些清理            catch (BeansException ex) {                logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);                // 我需要将我创建的bean销毁掉                destroyBeans();                // 我不再活跃                cancelRefresh(ex);                // 我要告诉你,我出异常了,救我!!                throw ex;            }            finally {                // 一些通用的缓存清掉!!                resetCommonCaches();            }        }    }

下面, 我来告诉你每个函数我到底做了哪些见不得人的事==, ready?go!!

prepareRefresh();

protected void prepareRefresh() {        this.startupDate = System.currentTimeMillis();        this.active.set(true);        if (logger.isInfoEnabled()) {            logger.info("Refreshing " + this);        }        // 初始化占位符placeHolder源头        initPropertySources();        // 验证一些必要属性, 当然这些必要属性是你告诉我的哦        getEnvironment().validateRequiredProperties();        // 诶呀,我在刷新的时候事件管理器还没做好呢,我得先创建一个临时的池子,好让在没创建事件管理器之前将需要发布的事件存起来啊!        this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();}

好的,到了这里我要开始刷新整个ApplicationContext了。

  1. 首先,我会记录下刷新时间,将ApplicationContext标志为活跃状态
  2. 然后,我在解析配置文件中的placeHolder的时候,会需要一些资源,所以,我会初始化 PropertySources, 该函数默认为空实现protected,表明是留给子类实现的,比如web里面的上下文什么的
  3. 接下来,我要验证一下我需要的一些必要属性有没有设置,如果没有设置,我是不会让你继续下去的,直接抛个MissingRequiredPropertiesException异常给你玩
  4. 最后,我将初始化一下我接受事件的载体earlyApplicationEvents,这玩意里面将保存所有的通过AbstractApplicationContext: publishEvent(ApplicationEvent event)来publish的事件

到了这里,我准备刷新的工作做完了,这边真的开始刷新了哦

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {        // 刷啊刷        refreshBeanFactory();        // 刷完了,可以出锅了        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        if (logger.isDebugEnabled()) {            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);        }        return beanFactory;    }

我刷新完工厂,然后将工厂返回,跟我走, 看看在refreshBeanFactory()里面做了哪些事情

AbstractRefreshableApplicationContext.java

 protected final void refreshBeanFactory() throws BeansException {        // 什么?我之前创建过工厂?销毁掉产品,关掉它!        if (hasBeanFactory()) {            destroyBeans();            closeBeanFactory();        }        try {            // 开始创办工厂!            DefaultListableBeanFactory beanFactory = createBeanFactory();            // 给工厂取个名字呗            beanFactory.setSerializationId(getId());            // 来,给你特殊定制一下            customizeBeanFactory(beanFactory);            // 加载创建产品(bean)需要的原料(beanDefinition)            loadBeanDefinitions(beanFactory);            synchronized (this.beanFactoryMonitor) {                this.beanFactory = beanFactory;            }        }        catch (IOException ex) {            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);        }}
  1. 首先,我会检查一下我之前有木有创建过Bean工厂,如果创建过,那么我要先将ta销毁,销毁的意思嘛,就是将我bean工厂里面的所有的单例bean全清除掉哦,然后将工厂关闭,就是把我的bean工厂的名字也抹掉啦
  2. 然后,我要开始创建新的bean工厂了,第7行中,我要先把厂子搭建好,这样,才能容得下之后的bean啊,这里偷偷告诉大家,这里创建出来的DefaultListableBeanFactory可是重量级嘉宾,你用到的许许多多的bean什么的都是这家伙搞出来的呢
  3. 接下来呢,我就给工厂取个好听的名字,然后将你告诉我的两样重要的事情转达给bean工厂
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {        if (this.allowBeanDefinitionOverriding != null) {            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);        }        if (this.allowCircularReferences != null) {            beanFactory.setAllowCircularReferences(this.allowCircularReferences);        }    }

这两件重要的事情就是,该工厂是否可以支持Bean定义的覆盖,即是否可以在不同的配置文件里面定义两个相同名字的的bean;是否支持循环引用,循环引用的意思是A依赖B,B依赖C,结果又发现C依赖A,那就说明A产生了循环依赖,我在解决循环依赖这方面可是很牛逼的,以后有时间我会慢慢向你诉说。
4. 最后,我就开始装载bean原料(BeanDefinition)了,在这里提一下,很重要的哦,我在创建每个bean的时候,会先将所有bean的原料选准备好,包括bean里面所有属性的描述,构造防范的描述,依赖关系的描述,我都给抽象好,以便之后我创建bean的时候直接拿来用

loadBeanDefinitions(beanFactory);

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {        // 创造一个xml读取器,为我的工厂读取配置        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);        // Configure the bean definition reader with this context's        // resource loading environment.        beanDefinitionReader.setEnvironment(this.getEnvironment());        beanDefinitionReader.setResourceLoader(this);        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));        // Allow a subclass to provide custom initialization of the reader,        // then proceed with actually loading the bean definitions.        initBeanDefinitionReader(beanDefinitionReader);        loadBeanDefinitions(beanDefinitionReader);    }

装载bean原料(BeanDefinition)的时候,我要先创造一个读取器(BeanDefinitionReader)来帮载入资源(Resource),大多数情况下,我一般用xml读取器(XmlBeanDefinitionReader)来读取资源。创建好了资源读取器之后,给这个资源读取器设置一些环境啦(Environment),资源加载器啦(ResourceLoader, 为了让资源读取器在读取到import之类引入其他资源的时候可以通过location转换为Resource),还有读取xml的一些辅助(EntityResolver),最终会进入到

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {        Resource[] configResources = getConfigResources();        if (configResources != null) {            reader.loadBeanDefinitions(configResources);        }        String[] configLocations = getConfigLocations();        if (configLocations != null) {            reader.loadBeanDefinitions(configLocations);        }    }

reader可以根据Resource来载入bean原料,也可以根据location来载入bean原料(想想为什么,上面我告诉过你的哦),好了,再跟下去估计你要晕了,就到这里了,总结一下,获取bean 工厂就是先搭一个厂子,然后通过bean原料读取器将bean原料载入到bean工厂里面,有了这个bean原料,后面我可以做很多很多事情。

我们继续回到牛逼哄哄的refresh方法,到了下面这一行, 函数体过于庞大,但都是纸老虎,不要怕!

prepareBeanFactory(beanFactory);

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {        // 我需要只要我在创造bean的时候用啥来加载        beanFactory.setBeanClassLoader(getClassLoader());        // 我还有el表达式(#{})的功能哦,这里就详细说el是啥玩意啦,自己百度哦        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));        // 属性转换器注册中心,用来注册属性转换器,比如'1989-07-30'转换为Date类型啦,你得告诉我怎么转换才行呀        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));        // 特殊的bean后置处理器,用来在bean初始化前后做一些手脚,这个ApplicationContextAwareProcessor        // 的主要作用就是给实现了某些特殊接口的bean注入一些特殊的bean        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));        // 忽略的依赖        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);        // 特殊的依赖规则        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);        beanFactory.registerResolvableDependency(ResourceLoader.class, this);        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);        beanFactory.registerResolvableDependency(ApplicationContext.class, this);        // AOP相关的一些东西,可以先不用关注        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));            // Set a temporary ClassLoader for type matching.            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));        }        // 注入环境相关的一些bean        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());        }        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());        }        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());        }    }
  1. 设置类加载器,用于之后bean原料的加工制作
  2. 设置el表达式(类似#{key})解析器
  3. 设置属性编辑器注册中心,属性编辑器这玩意主要用于属性从一种形式转换成另外一种形式,比如从
    ‘2015-11-26 21:29:11’转换成为一个合法的java.util.Date 类型,我内置了很多属性编辑器哦
  4. 注入Bean后置处理器(BeanPostProcessor), 关于BeanPostProcessor的具体用法后面会具体描述,这里简单提一下哦,这个BeanPostProcessor在Bean实例化之前之后可以做一些定制化的操作,从字面意思上来看,ApplicationContextAwareProcessor要做的事情就是给实现了与ApplicationContext相关接口的bean注入一下上下文信息,比如环境呀,工厂呀,上下文呀什么的
  5. 下面这五行我会告诉bean工厂,你在解决bean的依赖关系的时候,如果碰到了ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware,EnvironmentAware就不要试图取获取这些bean啦,直接忽略掉就行了
  6. 上面我告诉bean工厂忽略掉一些bean依赖的注入,下面我同样会告诉bean工厂,你在解决下面几个依赖的时候,直接把我告诉你的bean拿去用就行啦,这些bean都是与上下文相关的BeanFactory, ResourceLoader, ApplicationEventPublisher, ApplicationContext, 猜一下,为啥第二个参数中有this?那就说明我(作为ApplicationContext)同时具有这三者的功能啦,是时候告诉你我是谁了!后面几行也就是注册了几个单例,加载环境信息啦,没啥好说的。好,放大招,看看我是谁啦
    ApplicationContext
    我又可以发布事件ApplicationEventPublisher, 又可以通过文件路径解析资源ResourcePatternResolver, 还可以处理国际化MessageSource, 还可以创建bean,获取beanListableBeanFactory,并且我可以告诉你我的父工厂是谁HierarchicalBeanFactory, 甚至可以告诉你我现在处在什么环境中 EnvironmentCapable,好啦,我是不是很牛逼,算了,低调,低调,哈哈哈

可以看到,我内部的对象管理也是通过注册bean来实现的哦,和你定义的bean没啥本质区别啦

晕啊晕,赶紧回忆一下我们到讲到哪一行了,快看,还是在refresh方法里面没出来啊==

postProcessBeanFactory(beanFactory);

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}

是的,你没看错,这行里面啥都没,但是,仔细看哦,这个是protected方法,你懂的,我可以留给我的子类来扩展这个方法做一些更牛逼的事情

转啊转,转到下面这一行,这一行告诉你,我的工厂中制作bean的原料(BeanDefinition)准备好了, 准备好之后,我可以给你一个机会更改这些原料,你通过向我注册BeanFactoryPostProcessor就可以达到你不可告人的秘密, 在这里,你可以做任何事情,甚至将我的工厂炸毁掉也行啊(搞坏所有的原料)

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

好了,还是看看我是怎么调用你给我注册的这些后置处理器的吧

invokeBeanFactoryPostProcessors(beanFactory);

调用

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());}

继续转啊转转到这个类

PostProcessorRegistrationDelegate.java

这个类是在2013-8-28,Juergen Hoeller 这家伙重构过的, since spring 4.0,主要处理一些后置处理器相关的复杂的操作,由于函数体过于庞大,这里我就带你深入到内部去剖析,带你装逼带你飞

首先,我简要的告诉你这段代码做了什么事情,看到传入的beanFactoryPostProcessors参数没有,所有的beanFactoryPostProcessor中,他们是最先被执行的哦,他们是通过调用

AbstractApplicationContext

public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) {        this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);}

加入到成员变量 beanFactoryPostProcessors, 然后通过

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {        return this.beanFactoryPostProcessors;}

传到这里来的

这里的 BeanFactoryPostProcessors 可以分为两种,一种是非常普通的,一种是BeanDefinitionRegistryPostProcessor, 字面上意思也可以看的出来,这玩意功能更多呀,
主要多了 postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 这么一个方法, 基本上可以猜出来这个方法是给你注册bean原料(beanDefinition用的哦)
下面的调用比较复杂,我大概和你先讲下做了什么事情

首先呢,check一下我这个工厂是否有注册bean原料的能力(beanFactory instanceof BeanDefinitionRegistry))
如果有的话:
先处理通过addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) 注册进来的beanFactoryPostProcessors
处理的时候
如果该后置处理器是 BeanDefinitionRegistryPostProcessor, 先调用它的postProcessBeanDefinitionRegistry方法,由于它又是一个BeanFactoryPostProcessor
所以要将它榨干registryPostProcessors.add(registryPostProcessor);, 以便接下来再调用它的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)的功能
如果是普通的beanFactoryPostProcessors, 保留起来, 然后,按照如下优先级依次调用
1. 实现了PriorityOrdered接口(调用之前先排序)
2. 实现了Ordered接口(调用之前先排序)
3. 普通的BeanDefinitionRegistryPostProcessor
最后,再次调用BeanDefinitionRegistryPostProcessor继承下来的BeanFactoryPostProcessor的功能,以及普通的beanFactoryPostProcessors

如果这个工厂没有注册bean原料的能力,那么说明后置处理器中不存在BeanDefinitionRegistryPostProcessor, 就直接将你通过addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor)
注册进来的beanFactoryPostProcess执行一遍啦

好了,上面是处理通过addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor)注册进来的beanFactoryPostProcess
以及BeanDefinitionRegistryPostProcessor, 接下来便是处理普通的BeanFactoryPostProcessor
这边处理流程就比较简单了,处理顺序为
1. 实现了PriorityOrdered接口(调用之前先排序)
2. 实现了Ordered接口(调用之前先排序)
3. 普通的BeanFactoryPostProcessor

下面,我带着你分析每一行代码

    public static void invokeBeanFactoryPostProcessors(            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {        // 用于记录处理过的beanFactoryPostProcessors,最简单的防止重复处理的办法就是处理完扔到这里面然后每次处理之前看看这里面有没有,有就不处理        Set<String> processedBeans = new HashSet<String>();        // 如果实现了BeanDefinitionRegistry接口, 那就需要处理BeanDefinitionRegistryPostProcessor, 因为BeanDefinitionRegistryPostProcessor        // 主要就是用来注册BeanDefinitionRegistry的        if (beanFactory instanceof BeanDefinitionRegistry) {            // 强制转换一下,以便当参数传给 BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry的方法            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;            // 记录普通的BeanFactoryPostProcessor            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();            // 记录处理过的BeanDefinitionRegistryPostProcessor, 主要是为了之后调用它继承自BeanFactoryPostProcessor的            // postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法,             List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =                    new LinkedList<BeanDefinitionRegistryPostProcessor>();            /**             * BeanDefinitionRegistryPostProcessor 在任何常规的postProcessor之前执行             */            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {                    BeanDefinitionRegistryPostProcessor registryPostProcessor =                            (BeanDefinitionRegistryPostProcessor) postProcessor;                    registryPostProcessor.postProcessBeanDefinitionRegistry(registry);                    // 处理完之后要榨干它哦                    registryPostProcessors.add(registryPostProcessor);                }                else {                    regularPostProcessors.add(postProcessor);                }            }            // 获取用户通过非api的方式注册的BeanDefinitionRegistryPostProcessor, 非api的意思就是在xml获取通过注解的方式            // 向我隐式注册, 比如你定义一个类实现了BeanDefinitionRegistryPostProcessor接口,并且这个类对应的bean被我管理,我            // 在这里就可以拿到            String[] postProcessorNames =                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);            // 记录实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor            List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();            for (String ppName : postProcessorNames) {                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {                    priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));                    // 要记录一下,这个BeanDefinitionRegistryPostProcessor已经被处理完了哦                    processedBeans.add(ppName);                }            }            // 按照getOrder返回的整数从小到大排序,最小的先执行            sortPostProcessors(beanFactory, priorityOrderedPostProcessors);            // 榨取,继续榨取            registryPostProcessors.addAll(priorityOrderedPostProcessors);            // 好了,终于可以执行了            invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);            // 记录实现了Ordered接口的BeanDefinitionRegistryPostProcessor            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);            List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();            for (String ppName : postProcessorNames) {                // 处理之前呢,要看下这个BeanDefinitionRegistryPostProcessor之前有木有处理过哦                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {                    orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));                    processedBeans.add(ppName);                }            }            // 按照getOrder返回的整数从小到大排序,最小的先执行            sortPostProcessors(beanFactory, orderedPostProcessors);            // 榨取,继续榨取            registryPostProcessors.addAll(orderedPostProcessors);            // 好了,终于可以执行了            invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);            // 最后呢,处理常规的BeanDefinitionRegistryPostProcessor            // 等等,这里为毛这么复杂,还有while循环啊!!!请记住BeanDefinitionRegistryPostProcessor可以干些什么事情哦            // 它可以向我注册bean,万一某个BeanDefinitionRegistryPostProcessor(假设叫A)向我注册的bean的是BeanDefinitionRegistryPostProcessor类型的bean呢(假设为B),按照            // 约定,我也必须搞一遍B啊,那玩意搞B的时候,这个B又向我注册了一个C,按照约定,我必须要再搞一遍C啊,万一C..            // 所以,这边就有个循环啦,直到我把所有的BeanDefinitionRegistryPostProcessor搞完,就结束啦            /**这里是为了保证自定义的postProcessBeanDefinationRegistry里面可能注册beanPostProcessor**/            boolean reiterate = true;            while (reiterate) {                reiterate = false;                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);                for (String ppName : postProcessorNames) {                    // 如果以前处理过就不处理                    if (!processedBeans.contains(ppName)) {                        BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);                        // 榨取哦                        registryPostProcessors.add(pp);                        // 记录一下我搞过这个家伙                        processedBeans.add(ppName);                        // 搞之                        pp.postProcessBeanDefinitionRegistry(registry);                        // 搞它的时候它又生出来一个,那我就循环搞它生出来的                        reiterate = true;                    }                }            }            // 搞定从BeanDefinitionRegistryPostProcessor搞榨取出来的普通的postProcessBeanFactory方法            invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);            // 搞定BeanFactoryPostProcessor方法            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);        }        else {            // 如果该工厂没有实现了BeanDefinitionRegistry接口,那就不需要处理BeanDefinitionRegistryPostProcessor            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);        }        // 拿到所有的BeanFactoryPostProcessor        String[] postProcessorNames =                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);        // 用三个List记录三种不同类型的BeanFactoryPostProcessor的bean或者名字        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();        List<String> orderedPostProcessorNames = new ArrayList<String>();        List<String> nonOrderedPostProcessorNames = new ArrayList<String>();        for (String ppName : postProcessorNames) {            if (!processedBeans.contains(ppName)) {                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {                    priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));                } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {                    orderedPostProcessorNames.add(ppName);                } else {                    nonOrderedPostProcessorNames.add(ppName);                }            }        }        // 执行priorityOrderedPostProcessors之前先排序         sortPostProcessors(beanFactory, priorityOrderedPostProcessors);        // 执行priorityOrderedPostProcessors        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);        // 搞orderedPostProcessors         List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();        for (String postProcessorName : orderedPostProcessorNames) {            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));        }        sortPostProcessors(beanFactory, orderedPostProcessors);        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);        // 搞普通的BeanFactoryPostProcessors.        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();        for (String postProcessorName : nonOrderedPostProcessorNames) {            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));        }        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);        // 清除缓存数据        beanFactory.clearMetadataCache();    }

整个过程,其实还蛮清晰流畅的嘛

好了,接下来我们看下refresh里面下一个函数, 同样又是重量级嘉宾, 但是,当你看懂了beanFactory的后置处理器,来分析这段代码,简直小菜一碟

registerBeanPostProcessors(beanFactory)

    public static void registerBeanPostProcessors(            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {        // 首先拿到所有的BeanPostProcessor        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);        // 这里可以不用细看,主要是做postProcessor的check        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));        // 开始分类        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();        // 主要保存MergedBeanDefinitionPostProcessor这以特殊的后置处理器        List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();        List<String> orderedPostProcessorNames = new ArrayList<String>();        List<String> nonOrderedPostProcessorNames = new ArrayList<String>();        for (String ppName : postProcessorNames) {            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);                priorityOrderedPostProcessors.add(pp);                if (pp instanceof MergedBeanDefinitionPostProcessor) {                    internalPostProcessors.add(pp);                }            }            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {                orderedPostProcessorNames.add(ppName);            }            else {                nonOrderedPostProcessorNames.add(ppName);            }        }        // 对实现了PriorityOrdered的BeanPostProcessor排序        sortPostProcessors(beanFactory, priorityOrderedPostProcessors);        // 注册实现了PriorityOrdered的BeanPostProcessor        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);        // 拿到实现了Ordered接口的BeanPostProcessor         List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();        for (String ppName : orderedPostProcessorNames) {            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);            orderedPostProcessors.add(pp);            // 如果这个BeanPostProcessor还实现了BeanPostProcessor接口,保留下来            if (pp instanceof MergedBeanDefinitionPostProcessor) {                internalPostProcessors.add(pp);            }        }        // 对实现了PriorityOrdered接口的BeanPostProcessor排序        sortPostProcessors(beanFactory, orderedPostProcessors);        // 注册实现了PriorityOrdered接口的BeanPostProcessor        registerBeanPostProcessors(beanFactory, orderedPostProcessors);        // 拿到普通的BeanPostProcessor        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();        for (String ppName : nonOrderedPostProcessorNames) {            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);            nonOrderedPostProcessors.add(pp);            // 如果这个BeanPostProcessor还实现了MergedBeanDefinitionPostProcessor接口,保留下来            if (pp instanceof MergedBeanDefinitionPostProcessor) {                internalPostProcessors.add(pp);            }        }        // 注册普通的BeanPostProcessor        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);        // 注册实现了MergedBeanDefinitionPostProcessor的接口,聪明的读者一定会有疑问,这里难道不会重复注册吗?        // 答案是不会, 因为注册的时候会先将之前注册的删掉的,我这么做的原因只是为了分类处理而已, 要将所有的        // MergedBeanDefinitionPostProcessor 放到最后处理        sortPostProcessors(beanFactory, internalPostProcessors);        registerBeanPostProcessors(beanFactory, internalPostProcessors);        // 最后,添加了一个特殊的后置处理器, 那么这个后置处理器必然最后一个被处理        // 用来注册实现了ApplicationListener接口的bean        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));    }

从上面的步骤可以看出和invokeBeanFactoryPostProcessors(beanFactory);的区别就是这边只是做一个注册而已,因为
BeanPostProcessor的功能是在bean初始化前后做一些手脚,那这边bean还没初始化呢,调用了有个毛用啊?

回到refresh() 继续下面一行

initMessageSource();

这一行主要是拿到与i18n,即国际化相关的bean, 如果你定义了,我就拿过来注册上去,如果没有定义, 那么我就自己搞出来一个空的,
所有的实现都是继承自父bean

    protected void initMessageSource() {        // 拿到工厂        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {        // 如果你定义,就拿过来            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);            // 如果我有父亲,并且这个国际化的bean也有层次, 那么就将我父亲的国际化bean设置为这个国际化bean的父亲            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;                if (hms.getParentMessageSource() == null) {                    hms.setParentMessageSource(getInternalParentMessageSource());                }            }            if (logger.isDebugEnabled()) {                logger.debug("Using MessageSource [" + this.messageSource + "]");            }        }        else {        //  定义一个空的            DelegatingMessageSource dms = new DelegatingMessageSource();            // 我将我父亲的国际化bean拿来作为这个空的国际化bean,这样所有的国际化操作都通过我父亲的国际化bean            dms.setParentMessageSource(getInternalParentMessageSource());            this.messageSource = dms;            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);            if (logger.isDebugEnabled()) {                logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +                        "': using default [" + this.messageSource + "]");            }        }    }

继续refresh() 中的下一行

initApplicationEventMulticaster()

注册事件管理器bean,和上面国际化bean差不多的实现, 如果你注册了,我就直接拿来用,否则我就自己创建一个默认的

    protected void initApplicationEventMulticaster() {        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {            this.applicationEventMulticaster =                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);            if (logger.isDebugEnabled()) {                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");            }        }        else {            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);            if (logger.isDebugEnabled()) {                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +                        "': using default [" + this.applicationEventMulticaster + "]");            }        }    }

refresh()方法下一行

onRefresh();

    protected void onRefresh() throws BeansException {        // For subclasses: do nothing by default.    }

里面啥都没,又是为了给我子类作为扩展!!

继续refresh()方法下一行

registerListeners();

就是注册事件监听器啦, 也没啥牛逼的

    protected void registerListeners() {        // 先注册你手工注册的监听器        for (ApplicationListener<?> listener : getApplicationListeners()) {            getApplicationEventMulticaster().addApplicationListener(listener);        }        // 再注册在配置文件或者注解里面的监听器        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);        for (String listenerBeanName : listenerBeanNames) {            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);        }        // 因为到了这里,我们终于有了一个事件管理器了,我们早先定义的earlyApplicationEvents        // 可以下岗了,下岗之前,别忘了要把它手中的任务先完成哦        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;        this.earlyApplicationEvents = null;        if (earlyEventsToProcess != null) {            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {                getApplicationEventMulticaster().multicastEvent(earlyEvent);            }        }    }

继续refresh()方法下一行

finishBeanFactoryInitialization(beanFactory);

在这个函数中,我把那些需要提前实例化的bean预先实例化, 啥叫需要提前实例化?要满足三个条件, 非抽象并且lazy-init为false
的单例

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {        // 注册转换服务, 这个和之前提到的属性编辑器是差不多的东西        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {            beanFactory.setConversionService(                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));        }        // 和AOP相关的功能, 先忽略吧        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);        for (String weaverAwareName : weaverAwareNames) {            getBean(weaverAwareName);        }        // 待定...        beanFactory.setTempClassLoader(null);        // 冻结所有的配置, 不能再修改任何配置啦, 因为接下来我就要实例化bean了啊!!        beanFactory.freezeConfiguration();        // 实例化需要实例化的bean        beanFactory.preInstantiateSingletons();    }

关于实例化bean,之后会详细分析.
我们可以看到,我在处理bean的时候,是先将配置文件或者注解什么的元数据(BeanDefinition)先准备好, 在实例化bean之前,又留了
两大扩展 BeanFactoryPostProcessor 和BeanPostProcessor 给你做扩展, 最后,我的依赖关系也是在实例化bean的时候完成的,之前
准备BeanDefinition的时候并没有去解决依赖关系,只是声明了,啊,谁依赖谁,这样子.

refresh() 下一行, 终于结束整个上下文的刷新啦!

finishRefresh();

    protected void finishRefresh() {        // 初始化生命周期处理器, 和注册国际化bean以及事件监听器一个套路了        initLifecycleProcessor();        // 生命周期处理器开始工作啦,如果你的bean实现了lifecycle接口, 并且现在是非运行状态,它会调用你的run方法哦        getLifecycleProcessor().onRefresh();        // 宣告天下,上下文刷新成功,跪舔吧,骚年!!        publishEvent(new ContextRefreshedEvent(this));        // 待定        LiveBeansView.registerApplicationContext(this);    }

以上任何异步出现异常,我都会清理掉这个过程中产生的垃圾,并把工厂关闭!由下面几行异常处理函数来处理

    catch (BeansException ex) {        logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);        // 销毁这个过程中产生的bean,因为产生的bean可能是残废的(依赖关系没有注入成功的)        destroyBeans();        // 关掉这个场吧        cancelRefresh(ex);        throw ex;    }

最终,将一些common的缓存清理掉, 这里我还得继续研究…

            finally {                // Reset common introspection caches in Spring's core, since we                // might not ever need metadata for singleton beans anymore...                resetCommonCaches();            }

至此,我的核心框架已经全部向你展示完毕,怎样?是不是so easy, 接下来,我会详细剖析每一个部分的实现细节,敬请期待!

欢迎加群了解如何开始你的第一份源码之旅
白话文讲spring

2 0
原创粉丝点击