Spring源码解析系列之IOC容器(一)

作者: 后厂村老司机 | 来源:发表于2018-06-02 16:29 被阅读185次

    前言

    实际上我所有的博客都是原来对原来印象笔记里笔记内容的加工,关于Spring源码自己已经解析了很多遍,但是时间长总是忘记,写一篇博客权当加强记忆,也算再次学习下大师们的设计思想,思考方式。本次源码解析对最底层的如怎么读取xml文件等不做详细解释,只分析关键步骤和思想。

    1、Spring整体架构

    Spring整体架构
    Spring由很多模块组成,我们不可能挨个模块去看源码去分析,看源码本身就是一件及其枯燥乏味的事情。言简意赅,咱们Spring源码解析系列只挑干货,即Core Container模块的IOC依赖注入,AOP模块的面向切面编程,DataAccess模块的Trasactions事务原理和web模块的mvc原理部分。而且分析也尽量偏向重要步骤和思想,而不是干巴巴的啃源码。
    源码分析思路:
    首先:确定IOC容器做了什么,其实主要是加载和管理bean
    然后:找到做这些事情的所有顶层接口
    再次:找顶层接口的干不同事情的子类、分析这些子类是做什么的
    最后:挑最富有内涵的接口分析其原理和思想,学习他们的设计思路

    2、IOC容器

    2.1、IOC的概念

    IOC即依赖注入、控制反转,两个概念都一样,即把创建Java对象和维持对象的依赖关系的活儿交给Spring来做,把对对象的控制权交给Spring、让对象减少耦合。我们这里把IOC叫做容器,即容纳Java Bean的容器。IOC容器里面所有能提供服务的对象都叫Bean,至于怎么配置Bean这里就不过多赘述了,如果你不知道通过xml和注解配置bean那么你不应该来看源码。

    2.2、bean的几种形态

    IOC里最重要的概念就是Bean,所有的接口都围绕Bean确立,在真正分析之前我们先看看Bean的几种形态。

    • 形态一:xml或者注解标注的概念态,此时bean只是一个由类和一些描述文件定义的概念状态,比如:
    <bean id="schedulerFactoryBean"
            class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="jobFactory" ref="jobFactory"></property>
    </bean>
    
    • 形态二:内存中的定义态,此时Bean被加载到内存中,但还处在BeanDefinition这种定义状态,这种状态实际上是bean创建的模板。
    • 形态三:纯净态,此时的Bean只是被Bean工厂创建成了对象,但是并没有给bean的每个属性赋值,此时各属性还处于0 null false等这种初始状态,想想无参构造函数创建的对象。
    • 形态四:成熟态,纯净的Bean的属性被赋予真实有效的值,此时的Bean就是我们最终要使用的状态,已经可以提供正常服务了。
    2.3、bean相关重要接口

    了解了Bean的几个状态后我们至少能想到几个重要的接口。

    • 接口一:Resource接口,能把xml等文件读取到内存中,并能够获取到xml文件的详细信息。
    • 接口二:Document接口,用于xml文件解析到内存,类似于js里的dom解析。
    • 接口三:BeanDefinitionReader接口,用于解析xml和加载Bean成为BeanDefinition
    • 接口四:BeanDefinition接口,bean的抽象定义,如是否单例,是否是懒加载,有哪些重要属性等等。
    • 接口五:BeanFactory,Spring里面的重要模式-工厂模式,用于创建真正意义上的bean类。
    • 接口六:ApplicationContext,应用程序上下文,我一般都把上下文理解成容器,这个容器就是bean真正运行的容器,spring机器也由此启动。
    2.4、bean创建步骤
    2.4.1、创建步骤

    上面我们了解了Bean的状态和几个处理Bean的工具,接着我们就看Bean是怎么从概念态变成可用的成熟态的。此处我们先以xml配置的bean为例子。

    • 步骤一:资源以统一资源接口Resource加载入内存,即利用Resource接口及其子类把xml加载到内存中。(形态一
    • 步骤二:把Resource处理成Document,然后根据Dom接口处理Element节点即可,然后校验,校验过程根据DTD和XSD也就是ApplicationContext头部的配置进行xml格式校验
    • 步骤三:解析,解析过程包括bean的id,property以及其他方面的配置,把资源中的bean和其他标签(是否懒加载,是否单例等)解析成BeanDefinition格式(形态二
    • 步骤四:注册、就是放到全局的Map中,不过注册之前做了重名校验,注册的方式有别名和bean名两种
    • 步骤五:解析注册完成之后通知监听器,这里只为后期扩展用,程序员可以实现相关监听器方法对这个事件进行处理
    • 步骤六:加载,加载步骤:注意:此时加载的Bean还没有被装载数据,还处于(形态三)纯净态
      (1):转换对应的beanname,也就是获取最终的beanname,别名转换,去掉无效标识符等
      (2):尝试从缓存中加载单例
      (3):Bean的实例化
      (4):原型模式的依赖检查
      (5):检测ParentBeanFactory,如果当前检测到的xml文件中不包含BeanName,就去父Factory中获取
      (6):将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
      (7):寻找依赖,先加载依赖的Bean
      (8):针对不同的scope进行bean的创建singleton,request等
      (9):类型转换
    • 步骤七:步骤六弄完bean就是成熟态了(形态四
    2.4.2、方法调用链:

    为了更好的阅读源码,此处先给出方法调用链


    spring方法调用链.png
    2.5、源码解读

    在开始阅读源码之前我们先来看看重要接口的继承体系(图片来源于网络,侵删)

    • A:Resource接口继承体系


      Resource接口UML图

      这个继承体系里有很多接口,但我们常用的接口是图中的蓝色部分,其中每个类都对应一种资源加载方式,比如URLResource可以从网络获取ApplicationContext.xml文件,FileSystemResource可以从本地文件系统获取xml。

    • B:BeanDefinitionReader接口继承体系


      BeanDefinitionReader接口继承体系

      这个体系就比较清楚了,XmlBeanDefinitionReader可以把xml文件中的bean加载到内存中,并可以处理Document文件。

    • C:BeanDefinition接口继承体系


      BeanDefinition接口继承体系

      直接关注RootBeanDefinition,该类利用其每个父类接口的技能来包装Bean的定义。比如定义xml的bean,还可以定义注解的bean。

    • D:BeanFactory接口继承体系


      BeanFactory接口继承体系

      BeanFactory接口里定义了多个BeanFactory,本质上是利用了设计模式基本原则里面的单一职责原则与接口隔离原则,简单来说就是每个接口都只干好自己的一滩事儿。比如:ListableBeanFactory可以枚举所有的BeanDefinition、AutowireCapableBeanFactory定义了各种装配规则,可以自动装配Bean、ConfigurableBeanFactory可配置的BeanFactory。他们的子类DefaultListableBeanFactory可以用调用每个接口的方法去应对不同的环境。就像郭靖有江南七怪七个老师,每个老师都有不同技能,所以郭靖可以对不同的环境使用不同老师的技能。

    • E:ApplicationContext接口继承体系


      ApplicationContext继承体系

      这个继承体系看起来复杂,但实际上许多类本质上是不同应用环境下的不同容器而已,比如WebApplication是应用于web应用中的Ioc容器、ClassPathXmlApplicationContext可以以项目中的.xml文件的配置创建一个IOC容器、FileSystemXMLApplicationContext可以根据磁盘的绝对路径获取.xml文件配置一个IOC容器。


    源码解读开始(以ClassPathXmlApplicationContext为例)

    step1:首先创建并初始化一个ClassPathXml的IOC容器

    public class HelloProgram {
        public static void main(String[] args) {
            //创建IOC容器
            ApplicationContext context =new ClassPathXmlApplicationContext("beans.xml");
            HelloWorldService service =(HelloWorldService) context.getBean("helloWorldService");
            HelloWorld hw= service.getHelloWorld();
            hw.sayHello();
        }
    }
    
    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
            this(new String[] {configLocation}, true, null);
    }
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
     //父容器被设置为Null
            super(parent);
    //存储了xml的位置,以便后续获取
            setConfigLocations(configLocations);
            if (refresh) {
    //常规操作,初始化容器,如果之前存在就销毁,不存在就创建
                refresh();
        }
    }
    
        @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // 预初始化,设置容器的启动时间、激活标志,初始化和验证一些预定义的属性(有的话)
                prepareRefresh();
    
                // 初始化BeanFactory,存在则销毁,不存在则创建一个
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // 对即将在IOC容器里使用的BeanFactory做一些配置,比如设置类加载器,设置回调方法等
                prepareBeanFactory(beanFactory);
    
                try {
                    // BeanFactory构建完成之后事件,这个方法没有实现,我们可以实现一个。
                    postProcessBeanFactory(beanFactory);
    
                    // I执行上面的事件
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // 在创建Bean过程中注册拦截器,这些个拦截器会在bean成为真正的成熟bean(applicationContext管理的bean)之前调用
                    registerBeanPostProcessors(beanFactory);
    
                    // 初始化信息源,信息源bean可以国际化的读取properties文件
                    initMessageSource();
    
                    // 初始化事件广播器,对于他内部的监听者applicationListeners,每次事件到来都会一一获取通知(这里使用了观察者模式)
                    initApplicationEventMulticaster();
    
                    // 模板方法模式,埋了一个钩子,那些想要实现特殊实例化bean的类可以重写这个方法以实现自己的定制化初始化方案
                    onRefresh();
    
                    // 给事件广播器注册一些监听器(观察者模式)
                    registerListeners();
    
                    // 完成BeanFacotry的初始化,初始化所有剩余的单例Bean
                    finishBeanFactoryInitialization(beanFactory);
    
                    //初始化容器的生命周期事件处理器,并发布容器的生命周期事件 
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    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;
                }
            }
        }
    

    obtainFreshBeanFactory方法调用链

    该方法为BeanFactory准备创建Bean的原材料,即BeanDefinition,准备好之后放到一个ConcurrentHashMap里面,key为beanName,value为BeanDefinition

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            refreshBeanFactory();
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (logger.isDebugEnabled()) {
                logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
            }
            return beanFactory;
        }
    
    protected final void refreshBeanFactory() throws BeansException {
            //如果已经存在BeanFactory那么就销毁
            if (hasBeanFactory()) {
                destroyBeans();
                closeBeanFactory();
            }
            try {
                //创建一个默认的BeanFactory,即全功能的那个郭靖!
                DefaultListableBeanFactory beanFactory = createBeanFactory();
                beanFactory.setSerializationId(getId());
                //配置beanFactory的一些定制化属性,如是否允许循环依赖,是否支持definition重写
                customizeBeanFactory(beanFactory);
                //这步就关键了,载入BeanDefinations,给BeanFactory工厂提供创建bean的原材料!
                loadBeanDefinitions(beanFactory);
                synchronized (this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }
            }
            catch (IOException ex) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
            }
        }
    
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
            // 为当前工厂创建一个BeanDefinition读取器!
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
            // 根据Contextn的资源对该读取器进行配置,得告诉他去哪读啊,怎么读啊!
            beanDefinitionReader.setEnvironment(this.getEnvironment());
            beanDefinitionReader.setResourceLoader(this);
            beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
            // 这里可以设置一个定制化的Reader
            initBeanDefinitionReader(beanDefinitionReader);
            //此处调用了重载的方法,把已经装饰好的能用的BeanDefinitionReader读取器当参数传了进去
            loadBeanDefinitions(beanDefinitionReader);
        }
    
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
            //这里的reader已经可以正常干活儿了,首先获取bean定义资源
            Resource[] configResources = getConfigResources();
            if (configResources != null) {
                reader.loadBeanDefinitions(configResources);
            }
            //显然这个configRuations我们之前给传了一个路径"bean.xml",所以执行这个重载方法
            String[] configLocations = getConfigLocations();
            if (configLocations != null) {
                reader.loadBeanDefinitions(configLocations);
            }
        }
        @Override
        public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
            Assert.notNull(locations, "Location array must not be null");
            int counter = 0;
            for (String location : locations) {
                counter += loadBeanDefinitions(location,null);
            }
            return counter;
        }
    

    尼玛,套路好深,一个loadBeanDefinition搞这么多重载方法,擦得,总算到底了

    public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
            ResourceLoader resourceLoader = getResourceLoader();
            if (resourceLoader == null) {
                throw new BeanDefinitionStoreException(
                        "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
            }
    
            if (resourceLoader instanceof ResourcePatternResolver) {
                // Resource pattern matching available.
                try {
                    Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
                    int loadCount = loadBeanDefinitions(resources);
                    if (actualResources != null) {
                        for (Resource resource : resources) {
                            actualResources.add(resource);
                        }
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                    }
                    return loadCount;
                }
                catch (IOException ex) {
                    throw new BeanDefinitionStoreException(
                            "Could not resolve bean definition resource pattern [" + location + "]", ex);
                }
            }
            else {
                // Can only load single resources by absolute URL.
                Resource resource = resourceLoader.getResource(location);
                int loadCount = loadBeanDefinitions(resource);
                if (actualResources != null) {
                    actualResources.add(resource);
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
                }
                return loadCount;
            }
        }
    

    忽略我上面说的到底了,尼玛!!!!到这应该算是到底了吧,这里调用的是XMLBeanDefinitionReader中的loadBeanDefinitions方法,里边用IO流来读取文件

    //该方法从我们指定的路径里获取xml的bean!!!
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
            Assert.notNull(encodedResource, "EncodedResource must not be null");
            if (logger.isInfoEnabled()) {
                logger.info("Loading XML bean definitions from " + encodedResource.getResource());
            }
    
            Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
            if (currentResources == null) {
                currentResources = new HashSet<EncodedResource>(4);
                this.resourcesCurrentlyBeingLoaded.set(currentResources);
            }
            if (!currentResources.add(encodedResource)) {
                throw new BeanDefinitionStoreException(
                        "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
            }
            try {
                InputStream inputStream = encodedResource.getResource().getInputStream();
                try {
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }
                    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                }
                finally {
                    inputStream.close();
                }
            }
            catch (IOException ex) {
                throw new BeanDefinitionStoreException(
                        "IOException parsing XML document from " + encodedResource.getResource(), ex);
            }
            finally {
                currentResources.remove(encodedResource);
                if (currentResources.isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }
            }
        }
    

    好吧,我们接着看下面的载入

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
            try {  
                //此处把xml文件通过IO流读入内存并处理成Document类型,后续就可以通过dom操作了
                Document doc = doLoadDocument(inputSource, resource);
                return registerBeanDefinitions(doc, resource);
            }catch(各种catch){
                          ..........
                    }
        }
    @SuppressWarnings("deprecation")
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            //创建一个解析Document的BeanDefinitionReader
            BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
            documentReader.setEnvironment(getEnvironment());
            int countBefore = getRegistry().getBeanDefinitionCount();
            //利用DocumentReader注册BeanDefinition
            documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
            return getRegistry().getBeanDefinitionCount() - countBefore;
        }
     @Override
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            logger.debug("Loading bean definitions");
            Element root = doc.getDocumentElement();
            doRegisterBeanDefinitions(root);
        }
    protected void doRegisterBeanDefinitions(Element root) {
            //实际上这里的root代表的是<beans>标签
            BeanDefinitionParserDelegate parent = this.delegate;
            this.delegate = createDelegate(getReaderContext(), root, parent);
            if (this.delegate.isDefaultNamespace(root)) {
                String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
                if (StringUtils.hasText(profileSpec)) {
                    String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                            profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                    if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                        return;
                    }
                }
            }
            preProcessXml(root);
            parseBeanDefinitions(root, this.delegate);
            postProcessXml(root);
    
            this.delegate = parent;
        }
    

    下面的方法利用迭代器迭代的把<beans>标签里的元素处理成内存中的BeanDefinition

    //真正解析bean标签的方法
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
            if (delegate.isDefaultNamespace(root)) {
                NodeList nl = root.getChildNodes();
                for (int i = 0; i < nl.getLength(); i++) {
                    Node node = nl.item(i);
                    if (node instanceof Element) {
                        Element ele = (Element) node;
                        if (delegate.isDefaultNamespace(ele)) {
                            parseDefaultElement(ele, delegate);
                        }
                        else {
                            delegate.parseCustomElement(ele);
                        }
                    }
                }
            }
            else {
                delegate.parseCustomElement(root);
            }
        }
    

    下面的方法会创建一个BeanDefinitionHolder持有BeanDefinition及名字,别名数组

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            //持有beanName,BeanDefinition和Bean的别名
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    // 把beanName-BeanDefinition键值对放到private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);里面
                    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
                }
                catch (BeanDefinitionStoreException ex) {
                    getReaderContext().error("Failed to register bean definition with name '" +
                            bdHolder.getBeanName() + "'", ele, ex);
                }
                // 发送注册成功信号,告知容器已经注册好了所有Bean成BeanDefinition了
                getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
            }
        }
    

    下面这个方法是最终解析xml成BeanDefinition!!!

    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
             //获取BeanID
                    String id = ele.getAttribute(ID_ATTRIBUTE);
                  //获取Bean的名字
            String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
              //获取bean的所有别名
            List<String> aliases = new ArrayList<String>();
            if (StringUtils.hasLength(nameAttr)) {
                String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                aliases.addAll(Arrays.asList(nameArr));
            }
            //如果bean没有名字其ID就是他的名字
            String beanName = id;
            if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
                beanName = aliases.remove(0);
                if (logger.isDebugEnabled()) {
                    logger.debug("No XML 'id' specified - using '" + beanName +
                            "' as bean name and " + aliases + " as aliases");
                }
            }
    
            if (containingBean == null) {
                checkNameUniqueness(beanName, aliases, ele);
            }
    
            AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
            if (beanDefinition != null) {
                if (!StringUtils.hasText(beanName)) {
                    try {
                        if (containingBean != null) {
                            beanName = BeanDefinitionReaderUtils.generateBeanName(
                                    beanDefinition, this.readerContext.getRegistry(), true);
                        }
                        else {
                            beanName = this.readerContext.generateBeanName(beanDefinition);
                            String beanClassName = beanDefinition.getBeanClassName();
                            if (beanClassName != null &&
                                    beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                                aliases.add(beanClassName);
                            }
                        }
                        if (logger.isDebugEnabled()) {
                            logger.debug("Neither XML 'id' nor 'name' specified - " +
                                    "using generated bean name [" + beanName + "]");
                        }
                    }
                    catch (Exception ex) {
                        error(ex.getMessage(), ele);
                        return null;
                    }
                }
                String[] aliasesArray = StringUtils.toStringArray(aliases);
            //返回BeanDefinationHolder
                return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
            }
            return null;
        }
    

    Ok以上代码都执行完BeanFactory的原材料算是准备好了,BeanFactory可以拿着这些原材料制作Bean了


    prepareBeanFactory方法解析:

    该方法为BeanFactory工厂设置类加载器、bean创建监听器、初始化一些IOC容器自带的必须要初始化的Bean

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            // Tell the internal bean factory to use the context's class loader etc.
            beanFactory.setBeanClassLoader(getClassLoader());
            beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
            beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    
            // Configure the bean factory with context callbacks.
            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 interface not registered as resolvable type in a plain factory.
            // MessageSource registered (and found for autowiring) as a bean.
            beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
            beanFactory.registerResolvableDependency(ResourceLoader.class, this);
            beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
            beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    
            // Detect a LoadTimeWeaver and prepare for weaving, if found.
            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()));
            }
    
            // Register default environment beans.
            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());
            }
        }
    

    finishBeanFactoryInitialization(beanFactory)方法分析

    该方法对那些非懒加载(spring默认)的Bean进行预实例化

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            // Initialize conversion service for this context.
            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));
            }
    
            // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
            String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
            for (String weaverAwareName : weaverAwareNames) {
                getBean(weaverAwareName);
            }
    
            // Stop using the temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(null);
    
            // Allow for caching all bean definition metadata, not expecting further changes.
            beanFactory.freezeConfiguration();
    
            // Instantiate all remaining (non-lazy-init) singletons.
            beanFactory.preInstantiateSingletons();
        }
    
    
    //对配置lazy-init属性Bean的预实例化  
    public void preInstantiateSingletons() throws BeansException {  
           if (this.logger.isInfoEnabled()) {  
               this.logger.info("Pre-instantiating singletons in " + this);  
           }  
           synchronized (this.beanDefinitionMap) {  
               for (String beanName : this.beanDefinitionNames) {  
                   //获取指定名称的Bean定义  
                   RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);  
                   //bean定义为非抽象,单例模式,非懒加载 
                   if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {  
                       //如果指定名称的bean是创建容器的Bean  
                       if (isFactoryBean(beanName)) {  
                       //FACTORY_BEAN_PREFIX=”&”,当Bean名称前面加”&”符号 时,获取的是产生容器对象本身,而不是容器产生的Bean.  
                      //调用getBean方法,触发容器对Bean实例化和依赖注入过程  
                           final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);  
                           //标识是否需要预实例化  
                           boolean isEagerInit;  
                           if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {  
                               //一个匿名内部类  
                               isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {  
                                   public Boolean run() {  
                                       return ((SmartFactoryBean) factory).isEagerInit();  
                                   }  
                               }, getAccessControlContext());  
                           }  
                           else {  
                               isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();   
                           }  
                           if (isEagerInit) {  
                              //调用getBean方法,触发容器对Bean实例化和依赖注入过程  
                               getBean(beanName);  
                           }  
                       }  
                       else {  
                            //调用getBean方法,触发容器对Bean实例化和依赖注入过程  
                           getBean(beanName);  
                       }  
                   }  
               }  
           }  
        }
    

    下面这老长代码我看着都害怕,这个方法是真正创建预实例化的Bean的方法,如果你嫌弃太长了,知道这句话也就差不多够了。这个bean是纯净态无污染的bean哦。我们关注下面方法里的单例模式的bean的创建,和原型模式的bean的创建,直接看关键代码(有注释的)

    @SuppressWarnings("unchecked")
        protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args,boolean typeCheckOnly) throws BeansException {
            final String beanName = transformedBeanName(name);
            Object bean;
            // Eagerly check singleton cache for manually registered singletons.
            Object sharedInstance = getSingleton(beanName);
            if (sharedInstance != null && args == null) {
                if (logger.isDebugEnabled()) {
                    if (isSingletonCurrentlyInCreation(beanName)) {
                        logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");
                    }
                    else {
                        logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                    }
                }
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }
            else {
                if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
                BeanFactory parentBeanFactory = getParentBeanFactory();
                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                    String nameToLookup = originalBeanName(name);
                    if (args != null) {
                        return (T) parentBeanFactory.getBean(nameToLookup, args);
                    }
                    else {
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                }
    
                if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }
                try {
                    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    checkMergedBeanDefinition(mbd, beanName, args);
                    String[] dependsOn = mbd.getDependsOn();
                    if (dependsOn != null) {
                        for (String dependsOnBean : dependsOn) {
                            if (isDependent(beanName, dependsOnBean)) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                            }
                            registerDependentBean(dependsOnBean, beanName);
                            getBean(dependsOnBean);
                        }
                    }
                                    //
                    if (mbd.isSingleton()) {
                        sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                try {
                                    return createBean(beanName, mbd, args);
                                }
                                catch (BeansException ex) {
                                    destroySingleton(beanName);
                                    throw ex;
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    }
    
                    else if (mbd.isPrototype()) {
                        Object prototypeInstance = null;
                        try {
                            beforePrototypeCreation(beanName);
                            prototypeInstance = createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    }
                    else {
                        String scopeName = mbd.getScope();
                        final Scope scope = this.scopes.get(scopeName);
                        if (scope == null) {
                            throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                        }
                        try {
                            Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                                @Override
                                public Object getObject() throws BeansException {
                                    beforePrototypeCreation(beanName);
                                    try {
                                        return createBean(beanName, mbd, args);
                                    }
                                    finally {
                                        afterPrototypeCreation(beanName);
                                    }
                                }
                            });
                            bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                        }
                        catch (IllegalStateException ex) {
                            throw new BeanCreationException(beanName,
                                    "Scope '" + scopeName + "' is not active for the current thread; " +
                                    "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                    ex);
                        }
                    }
                }
                catch (BeansException ex) {
                    cleanupAfterBeanCreationFailure(beanName);
                    throw ex;
                }
            }
            if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
                try {
                    return getTypeConverter().convertIfNecessary(bean, requiredType);
                }
                catch (TypeMismatchException ex) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Failed to convert bean '" + name + "' to required type [" +
                                ClassUtils.getQualifiedName(requiredType) + "]", ex);
                    }
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
            }
            return (T) bean;
        }
    

    为了上面的代码更容易观察,我们把单例模式bean创建过程提取出来,下面方法的createBean就是真正创建Bean的地方

                if (mbd.isSingleton()) {
                        sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                try {  
                    //真正创建Bean的地方,要把Bean和BeaNDefination信息传给这个方法
                                    return createBean(beanName, mbd, args);
                                }
                                catch (BeansException ex) {
                                    destroySingleton(beanName);
                                    throw ex;
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    }
    

    下面的代码就是真正执行BeanDefination到Bean实例化的代码,其中populateBean就是依赖注入发生的地方!!!!

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
            BeanWrapper instanceWrapper = null;
            if (mbd.isSingleton()) {
                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
            }
            if (instanceWrapper == null) {
            /**根据配置的Class信息创建一个实例包裹器,包裹器里包裹着一个实例化的bean,但此bean并没有被赋值**/
                instanceWrapper = createBeanInstance(beanName, mbd, args);
            }
        //获取到这个没有给属性赋值的纯净Bean
            final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
            Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
            synchronized (mbd.postProcessingLock) {
                if (!mbd.postProcessed) {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                    mbd.postProcessed = true;
                }
            }
            //如果bean涉及到了循环引用,而且是单例的,而且是在创建过程中,则允许该bean提前曝光,我们下一章会讲解Spring中的循环引用问题
            boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                    isSingletonCurrentlyInCreation(beanName));
            if (earlySingletonExposure) {
                ----------打印日志------------
                addSingletonFactory(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        return getEarlyBeanReference(beanName, mbd, bean);
                    }
                });
            }
    
            // 这里把刚刚创建好的bean进行装配,即使bean状态变成成熟态!!!
            Object exposedObject = bean;
            try {
            //使Bean变成成熟态的真正方法,即依赖注入的真正发生地!!!!!
                populateBean(beanName, mbd, instanceWrapper);
                if (exposedObject != null) {
            //对bean进行后置处理器处理
                    exposedObject = initializeBean(beanName, exposedObject, mbd);
                }
            }
            -----------捕获异常-------
            if (earlySingletonExposure) {
                Object earlySingletonReference = getSingleton(beanName, false);
                if (earlySingletonReference != null) {
                    if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                    }
                    else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                        String[] dependentBeans = getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                        for (String dependentBean : dependentBeans) {
                            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                actualDependentBeans.add(dependentBean);
                            }
                        }
                        if (!actualDependentBeans.isEmpty()) {
                            ----------------抛出异常-------------
                        }
                    }
                }
            }
            try {
                registerDisposableBeanIfNecessary(beanName, bean, mbd);
            }
            -------------捕获异常-----------------
            return exposedObject;
        }
    

    总结

    经过以上过程,Spring已经启动了一个全新的IOC容器,并把xml里配置的Bean从概念态转变为真正可用的成熟态并放到IOC容器里来管理了。我们可以通过getBean(“beanName”)来获取Bean的成熟态实例!

    相关文章

      网友评论

        本文标题:Spring源码解析系列之IOC容器(一)

        本文链接:https://www.haomeiwen.com/subject/teqlsftx.html