精华内容
下载资源
问答
  • springioc源码分析
    千次阅读
    2016-08-02 11:24:25

    参考链接

    Spring 启动入口

    ApplicationContext ac = new ClassPathXmlApplicationContext("......")
    ctx.getBean("xxx" , xxx.class);

    一般spring demo 都会选择这种启动方式,ClassPathXmlApplicationContext 就是spring源码分析的入口

    初始化源码分析

    public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
        private Resource[] configResources;
    
        // 去除各式各样的初始化函数
        ...
    
        public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
            super(parent);
            this.setConfigLocations(configLocations);
            if (refresh) {
                // 这个是核心入口,下面的初始化方法也出现了
                this.refresh();
            }
        }
    
        public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent) throws BeansException {
            super(parent);
            Assert.notNull(paths, "Path array must not be null");
            Assert.notNull(clazz, "Class argument must not be null");
            this.configResources = new Resource[paths.length];
    
            for(int i = 0; i < paths.length; ++i) {
                this.configResources[i] = new ClassPathResource(paths[i], clazz);
            }
    
            // refresh核心方法
            this.refresh();
        }
        ...
    }

    refresh 方法解析:

    public void refresh() throws BeansException, IllegalStateException {
            Object var1 = this.startupShutdownMonitor;
            synchronized(this.startupShutdownMonitor) {
    
                // 初始化前的准备操作,验证以及环境设置
                this.prepareRefresh();
    
                // 初始化BeanFactory,负责bean的生产和管理,是ioc的核心
                ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
    
                // beanFactory的功能的准备
                this.prepareBeanFactory(beanFactory);
    
                try {
                    //为子类设置BeanFactory的后置处理器
                    //子类覆盖方法做额外的处理。
                    postProcessBeanFactory(beanFactory);
    
                    //调用BeanFactoryPostProcessor,激活各种BeanFactory处理器
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register bean processors that intercept bean creation.
                    //注册拦截Bean创建的Bean处理器,这里只是注册,真正调用实在getBean的时候。
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.
                    //为上下文初始化Message源,国际化处理
                    initMessageSource();
    
                    // Initialize event multicaster for this context.
                    //初始化应用消息广播器,并放入applicationEventMulticaster bean中
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    // 留给子类来初始化其他的Bean
                    onRefresh();
    
                    // Check for listener beans and register them.
                    在所有注册的bean中查找Listener bean,注册到消息广播器中
                    registerListeners();
    
                    // Instantiate all remaining (non-lazy-init) singletons.
                    //初始化剩下的单实例,非惰性的
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.
                    完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
                    finishRefresh();
                } catch (BeansException var9) {
                    // 销毁beans
                    this.destroyBeans();
                    // 取消refresh
                    this.cancelRefresh(var9);
                    throw var9;
                } finally {
                    this.resetCommonCaches();
                }
            }
        }

    获取beanfactory:

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            // refresh beanFactory:参考AbstractRefreshableApplicationContext实现
            this.refreshBeanFactory();
    
            // 获取beanFactory,留给子类实现
            ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    
            return beanFactory;
        }

    refreshBeanFactory 的实现:

    protected final void refreshBeanFactory() throws BeansException {
            // 判断内置beanFactory对象引用
            if (this.hasBeanFactory()) { // 如果以及存在
                this.destroyBeans(); // 销毁关闭
                this.closeBeanFactory();
            }
    
            try {
                // 重新创建
                DefaultListableBeanFactory beanFactory = this.createBeanFactory();
                beanFactory.setSerializationId(this.getId());
                this.customizeBeanFactory(beanFactory);
                // 加载bean,由子类实现,可参考XmlBeanDefinitionReader实现
                this.loadBeanDefinitions(beanFactory);
                Object var2 = this.beanFactoryMonitor;
                synchronized(this.beanFactoryMonitor) {
                    // 同步赋值
                    this.beanFactory = beanFactory;
                }
            } catch (IOException var5) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
            }
        }

    loadBeanDefinitions 的具体实现:
    将资源转为BeanDefinition(bean定义实体),结果存放在Map中。

        public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return this.loadBeanDefinitions(new EncodedResource(resource));
        }
    
        public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
            Assert.notNull(encodedResource, "EncodedResource must not be null");
    
            // xml => resource
            Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
            if (currentResources == null) {
                currentResources = new HashSet(4);
                this.resourcesCurrentlyBeingLoaded.set(currentResources);
            }
    
            if (!((Set)currentResources).add(encodedResource)) {
                throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
            } else {
                int var5;
                try {
                    InputStream inputStream = encodedResource.getResource().getInputStream();
    
                    try {
                        InputSource inputSource = new InputSource(inputStream);
                        if (encodedResource.getEncoding() != null) {
                            inputSource.setEncoding(encodedResource.getEncoding());
                        }
                        // 实际上执行bean到resource对象的转换的方法
                        var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                    } finally {
                        inputStream.close();
                    }
                } catch (IOException var15) {
                    throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
                } finally {
                    ((Set)currentResources).remove(encodedResource);
                    if (((Set)currentResources).isEmpty()) {
                        this.resourcesCurrentlyBeingLoaded.remove();
                    }
    
                }
    
                return var5;
            }
        }
    
        // xml 解析
        protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
            try {
                // xml解析转为document
                Document doc = this.doLoadDocument(inputSource, resource);
                // 组装 + 注册(存放在Map)
                return this.registerBeanDefinitions(doc, resource);
            } 
            ...
        }

    registerBeanDefinitions 方法解析:

        public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            // BeanDefinitionDocumentReader 完成定义信息的解析和Bean信息的注册
            BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
            int countBefore = this.getRegistry().getBeanDefinitionCount();
            // 参考:DefaultBeanDefinitionDocumentReader
            documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
            return this.getRegistry().getBeanDefinitionCount() - countBefore;
        }

    registerBeanDefinitions的实现:

        public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            this.logger.debug("Loading bean definitions");
            Element root = doc.getDocumentElement();
            this.doRegisterBeanDefinitions(root);
        }
    
        protected void doRegisterBeanDefinitions(Element root) {
            BeanDefinitionParserDelegate parent = this.delegate;
            // 解析注册
            this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
            if (this.delegate.isDefaultNamespace(root)) {
                String profileSpec = root.getAttribute("profile");
                if (StringUtils.hasText(profileSpec)) {
                    String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
                    if (!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                        return;
                    }
                }
            }
    
            this.preProcessXml(root);// 自定义标签解析前置处理
            this.parseBeanDefinitions(root, this.delegate); //spring原标签处理
            this.postProcessXml(root);// 自定义标签解析后置处理
            this.delegate = parent;
        }

    实际解析大体流程:

     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)) {
                            this.parseDefaultElement(ele, delegate);
                        } else {
                            delegate.parseCustomElement(ele);
                        }
                    }
                }
            } else {
                delegate.parseCustomElement(root);
            }
        }
    
        private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
            if (delegate.nodeNameEquals(ele, "import")) {
                this.importBeanDefinitionResource(ele);
            } else if (delegate.nodeNameEquals(ele, "alias")) {
                this.processAliasRegistration(ele);
            } else if (delegate.nodeNameEquals(ele, "bean")) {
                // 解析注册
                this.processBeanDefinition(ele, delegate);
            } else if (delegate.nodeNameEquals(ele, "beans")) {
                // 递归
                this.doRegisterBeanDefinitions(ele);
            }
        }
    
        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    
                try {
                    // 实际注册代码
                    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
                } catch (BeanDefinitionStoreException var5) {
                    this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
                }
    
                this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
            }
    
        }

    注册bean

    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
            String beanName = definitionHolder.getBeanName();
            // 注册方法
            registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
            String[] aliases = definitionHolder.getAliases();
            if (aliases != null) {
                String[] var4 = aliases;
                int var5 = aliases.length;
    
                for(int var6 = 0; var6 < var5; ++var6) {
                    String alias = var4[var6];
                    registry.registerAlias(beanName, alias);
                }
            }
        }
    
        // BeanFactory 默认实现DefaultListableBeanFactory,实现了BeanDefinitionRegistry
        public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
            ...
            private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
            ...
        }
    

    put 方法:

                if (this.hasBeanCreationStarted()) {
                    Map var4 = this.beanDefinitionMap;
                    synchronized(this.beanDefinitionMap) {
                        this.beanDefinitionMap.put(beanName, beanDefinition);
                        List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                        updatedDefinitions.addAll(this.beanDefinitionNames);
                        updatedDefinitions.add(beanName);
                        this.beanDefinitionNames = updatedDefinitions;
                        if (this.manualSingletonNames.contains(beanName)) {
                            Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
                            updatedSingletons.remove(beanName);
                            this.manualSingletonNames = updatedSingletons;
                        }
                    }
                } else {
                    // 最终写入Map
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    this.beanDefinitionNames.add(beanName);
                    this.manualSingletonNames.remove(beanName);
                }

    初始化总结:
    1. 初始化的大体流程:资源定位、资源加载、注册
    2. refresh() 是核心函数
    3. beanDefinition最终存于Map

    获取bean源码分析

        public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
            return this.doGetBean(name, requiredType, args, false);
        }
    
        protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
            final String beanName = this.transformedBeanName(name);
            Object sharedInstance = this.getSingleton(beanName);
            Object bean;
            if (sharedInstance != null && args == null) {
                bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
            } else {
                if (this.isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
    
                BeanFactory parentBeanFactory = this.getParentBeanFactory();
                if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                    String nameToLookup = this.originalBeanName(name);
                    if (args != null) {
                        return parentBeanFactory.getBean(nameToLookup, args);
                    }
    
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
    
                if (!typeCheckOnly) {
                    this.markBeanAsCreated(beanName);
                }
    
                try {
                    final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                    this.checkMergedBeanDefinition(mbd, beanName, args);
                    String[] dependsOn = mbd.getDependsOn();
                    String[] var11;
                    if (dependsOn != null) {
                        var11 = dependsOn;
                        int var12 = dependsOn.length;
    
                        for(int var13 = 0; var13 < var12; ++var13) {
                            String dep = var11[var13];
                            if (this.isDependent(beanName, dep)) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                            }
    
                            this.registerDependentBean(dep, beanName);
                            this.getBean(dep);
                        }
                    }
    
                    if (mbd.isSingleton()) {
                        sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                            public Object getObject() throws BeansException {
                                try {
                                    return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                                } catch (BeansException var2) {
                                    AbstractBeanFactory.this.destroySingleton(beanName);
                                    throw var2;
                                }
                            }
                        });
                        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    } else if (mbd.isPrototype()) {
                        var11 = null;
    
                        Object prototypeInstance;
                        try {
                            this.beforePrototypeCreation(beanName);
                            prototypeInstance = this.createBean(beanName, mbd, args);
                        } finally {
                            this.afterPrototypeCreation(beanName);
                        }
    
                        bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    } else {
                        String scopeName = mbd.getScope();
                        Scope scope = (Scope)this.scopes.get(scopeName);
                        if (scope == null) {
                            throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                        }
    
                        try {
                            Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                                public Object getObject() throws BeansException {
                                    AbstractBeanFactory.this.beforePrototypeCreation(beanName);
    
                                    Object var1;
                                    try {
                                        var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
                                    } finally {
                                        AbstractBeanFactory.this.afterPrototypeCreation(beanName);
                                    }
    
                                    return var1;
                                }
                            });
                            bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                        } catch (IllegalStateException var21) {
                            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", var21);
                        }
                    }
                } catch (BeansException var23) {
                    this.cleanupAfterBeanCreationFailure(beanName);
                    throw var23;
                }
            }
    
            if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
                try {
                    return this.getTypeConverter().convertIfNecessary(bean, requiredType);
                } catch (TypeMismatchException var22) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
            } else {
                return bean;
            }
        }

    bean 作用域:

    • singleton
    • prototype

    bean 加载时机:

    • 延迟加载:第一次getBean的时候,才生成实例
    • 立即加载:在ioc初始化的时候,就生成实例
    更多相关内容
  • Spring IOC源码分析

    2021-11-26 17:42:46
    阅读前建议读者先掌握Spring中的基本概念,本文从源码角度分析IOC容器的创建过程,大体涉及两个重要部分,一个是Bean容器的创建,一个是Bean的生命周期,建议在阅读时自己跟着源码一起走一遍流程。 注意:因为版本的...

    阅读前建议读者先掌握Spring中的基本概念,本文从源码角度分析IOC容器的创建过程,大体涉及两个重要部分,一个是Bean容器的创建,一个是Bean的生命周期,建议在阅读时自己跟着源码一起走一遍流程。

    注意:因为版本的不同,源码小部分会有一定变化,不过不影响大体流程,核心部分都还是相同的。然后本文不对Spring中涉及的一些概念做解释,仅分析启动流程。

    让我们先来看一下最基本的Spring容器的demo

    public static void main(String[] args){
    	ApplicationContext context=new ClassPathXmlApplicationContext("classpath:application.xml");
    }
    

    整个容器启动流程就是从ClassPathXmlApplicationContext()这个构造开始,从类名来看很容易知道是在classpath中根据xml文件来构建ApplicationContext。除了xml的方式,还有其他方案可以选择。

    在这里插入图片描述

    我们可以看到,除了ClassPathXmlApplicationContext之外,还有FileSystemXmlApplicationContext和AnnotationConfigApplicationContext这两种配置方式,具体怎么使用请自行查阅资料。

    接下来还有一个比较重要的继承体系,就是BeanFactory,其实ApplicationContext也是一个BeanFactory

    在这里插入图片描述

    AutowireCapableBeanFatory就是用来自动装配Bean的。可以看到ApplicationContext并没有继承它,但是提供了一个特殊的方法getAutowireCapableBeanFactory()。另外两个二级接口ListableBeanFactory和HierarchicalBeanFactory,从名字可以看出来,一个是可以获取多个Bean,一个是可以将多个BeanFactory设置继承关系。BeanFactory做为顶层接口,只提供了获取单个Bean的接口,这也是最重要的一个方法getBean()。

    以上的继承体系请自行查阅源码,简单看下各个接口都提供哪些方法即可。

    启动流程分析

    容器的启动流程就是从ClassPathXmlApplicationContext的构造开始,

    	public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    		this(new String[] {configLocation}, true, null);
    	}
    
    	public ClassPathXmlApplicationContext(
    			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
    			throws BeansException {
    		super(parent);
            //根据路径进行分割,处理为配置文件数组
    		setConfigLocations(configLocations);
    		if (refresh) {
                //核心方法
    			refresh();
    		}
    	}
    

    refresh()是整个IOC的核心方法,为什么要叫refresh呢,是因为ApplicationContext可以重新创建,这样还会将原来的容器销毁,然后再执行一次初始化操作,这个操作就是刷新。

    	@Override
    	public void refresh() throws BeansException, IllegalStateException {
            //同步,避免启动和销毁是并发执行
    		synchronized (this.startupShutdownMonitor) {
                
                //刷新前的准备工作
    			prepareRefresh();
                
                //将配置文件解析成BeanDefinition对象,注册到BeanFactory中,并没有初始化Bean
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                
                //设置BeanFactory的类加载器,添加几个BeanPostProcessor,注册几个特殊的bean
    			prepareBeanFactory(beanFactory);
    			try {
                    //容器扩展点!!!
                    //如果Bean实现了BeanFactoryPostProcessor这个接口,那么在容器初始化后,
                    //Spring会调用实现类的postProcessBeanFactory方法。
                    //具体的子类可以在这一步注册特殊的BeanPostProcessors
    				postProcessBeanFactory(beanFactory);
                    
                    //回调BeanFactoryPostProcessor实现类的postProcessBeanFactory方法
    				invokeBeanFactoryPostProcessors(beanFactory);
                    
                    //注册BeanPostProcessor实现类,注意,一个是BeanFactory的后置处理器,
                    //一个是Bean的后置处理器。
                    //此接口的两个方法: postProcessBeforeInitialization和postProcessAfterInitialization
                    //分别在Bean的初始化之前和初始化之后执行。
    				registerBeanPostProcessors(beanFactory);
                    
                    //资源国际化,不重要
    				initMessageSource();
                    
                    //初始化Application的事件传播器,不是本期重点
    				initApplicationEventMulticaster();
                    
                    //钩子方法
                    //具体子类可以在这里初始化一些特殊的Bean
    				onRefresh();
                    
                    //注册事件监听器,需要实现ApplicationListener接口
    				registerListeners();
                    
                    //初始化所有的单例Bean,lazy-init除外
    				finishBeanFactoryInitialization(beanFactory);
                    
                    //广播事件,ApplicationContext完成初始化
    				finishRefresh();
    			}
    			catch (BeansException ex) {
    				if (logger.isWarnEnabled()) {
    					logger.warn("Exception encountered during context initialization - " +
    							"cancelling refresh attempt: " + ex);
    				}
                    //销毁已经初始化的单例Bean
    				destroyBeans();
    				cancelRefresh(ex);
    				throw ex;
    			}
    
    			finally {
    				resetCommonCaches();
    			}
    		}
    	}
    

    接下来按顺序解析重点方法

    prepareRefresh(),容器刷新前的准备工作

    	protected void prepareRefresh() {
            //记录刷新时间
    		this.startupDate = System.currentTimeMillis();
    		this.closed.set(false);
    		this.active.set(true);
    		//......
            
    		initPropertySources();
    
            //验证配置文件
    		getEnvironment().validateRequiredProperties();
    
    		//......
    	}
    

    obtainFreshBeanFactory(),创建容器并注册BeanDefinition

    #AbstractApplicationContext

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

    #AbstractRefreshableApplicationContext

    	@Override
    	protected final void refreshBeanFactory() throws BeansException {
            //如果已经创建过BeanFactory,就销毁所有Bean,关闭BeanFactory
            //这里指的是当前ApplicationContext中的BeanFactory
    		if (hasBeanFactory()) {
    			destroyBeans();
    			closeBeanFactory();
    		}
    		try {
                //创建一个DefaultListableBeanFactory对象,该方法仅创建了一个对象并返回
                //这里为什么要实例化DefaultListableBeanFactory?
                //请回到上面的继承图,可以发现该对象实现了所有的接口
    			DefaultListableBeanFactory beanFactory = createBeanFactory();
                
                //序列化
    			beanFactory.setSerializationId(getId());
                
                //设置BeanFactory的属性,是否允许Bean覆盖,是否允许循环引用
    			customizeBeanFactory(beanFactory);
                
                //加载BeanDefinition到BeanFactory中
    			loadBeanDefinitions(beanFactory);
                
                //将创建好的beanFactory赋值给当前ApplicationContext
                //虽然ApplicationContext也是BeanFactory的子接口,但其实是
                //内部持有一个BeanFactory的实例,具体操作都由该实例完成
    			this.beanFactory = beanFactory;
    		}
    		catch (IOException ex) {
    			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    		}
    	}
    

    在此处涉及到了BeanDefinition,BeanDefinition其实就是一个Bean的定义信息对象,它保存了用户在配置文件中定义好的Bean信息,例如这个Bean是属于哪个类,是否单例,是否懒加载等等。具体信息请自行查看BeanDefinition接口。

    接下来继续看customizeBeanFactory(beanFactory);

    	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    		if (this.allowBeanDefinitionOverriding != null) {
                //是否允许Bean定义覆盖
    			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    		}
    		if (this.allowCircularReferences != null) {
                //是否允许Bean的循环依赖
    			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    		}
    	}
    

    #AbstractXmlApplicationContext

    	@Override
    	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
            //创建XmlBeanDefinitionReader对象,用于从配置文件加载Bean信息并转成BeanDefinition
    		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
    		beanDefinitionReader.setEnvironment(this.getEnvironment());
    		beanDefinitionReader.setResourceLoader(this);
    		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    		initBeanDefinitionReader(beanDefinitionReader);
            //这个方法内部所有流程就是使用XmlBeanDefinitionReader对象,去解析
            //xml配置文件,并将文件中的bean信息转为BeanDefinition注册到BeanFactory中
            //内部涉及的都是一些解析工作,此处就不再展开
    		loadBeanDefinitions(beanDefinitionReader);
    	}
    

    到这里容器就已经创建完成了,并且容器保存了所有Bean的BeanDefinition信息。

    prepareBeanFactory(beanFactory),准备BeanFactory

    这一步也就是为BeanFactory进行一些设置

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    		//设置BeanFactory的类加载器
    		beanFactory.setBeanClassLoader(getClassLoader());
    		if (!shouldIgnoreSpel) {
    			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    		}
    		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    
    		//添加一个BeanPostProcessor,实现了Aware接口的Bean,在初始化时,由该processor进行回调
    		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        
        	//如果有Bean依赖于以下接口的实现类,在自动装配的时候忽略
    		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
    
    		//某些特殊的bean依赖下面几个,会注入响应的值。
        	//前面提到过的,ApplicationContext持有一个BeanFactory,就是这里的第一行
        	//并且ApplicationContext继承了后面的几个接口
    		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    		beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    
    		//注册监听器
    		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    
    		// Detect a LoadTimeWeaver and prepare for weaving, if found.
    		if (!NativeDetector.inNativeImage() && 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());
    		}
    		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
    			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
    		}
    	}
    

    prepareBeanFactory(beanFactory)方法执行完,后面的一些方法都只是一些注册处理器和处理回调,直接跳到

    finishBeanFactoryInitialization(beanFactory);

    finishBeanFactoryInitialization(beanFactory),初始化单例Bean

    到目前为止,BeanFactory已经创建完成,并且回调了BeanFactoryPostProcessor的postProcessBeanFactory()方法,初始化了BeanPostProcessor的实现类。加下来就是初始化单例Bean的流程。

    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));
    		}
    
    		if (!beanFactory.hasEmbeddedValueResolver()) {
    			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    		}
    
    		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    		for (String weaverAwareName : weaverAwareNames) {
    			getBean(weaverAwareName);
    		}
    
    		beanFactory.setTempClassLoader(null);
    
        	//冻结所有BeanDefinition,表明注册的BeanDefinition不会被进一步修改或后处理
    		beanFactory.freezeConfiguration();
    		
        	//初始化单例Bean
    		beanFactory.preInstantiateSingletons();
    	}
    

    #DefaultListableBeanFactory

    	@Override
    	public void preInstantiateSingletons() throws BeansException {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Pre-instantiating singletons in " + this);
    		}
    
    		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    		//触发非懒加载以外的单例bean初始化
    		for (String beanName : beanNames) {
                //合并父Bean的配置,<bean id="" class="" parent=""/>这里的parent
    			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                //非抽象,单例,非懒加载需要初始化
    			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    //是否是FactoryBean,不了解的请自行查阅概念
    				if (isFactoryBean(beanName)) {
                        //FactoryBean的beanName会在前面加上&符号,再调用getBean()
    					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    					if (bean instanceof FactoryBean) {
    						FactoryBean<?> factory = (FactoryBean<?>) bean;
    						boolean isEagerInit;
    						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
    							isEagerInit = AccessController.doPrivileged(
    									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
    									getAccessControlContext());
    						}
    						else {
    							isEagerInit = (factory instanceof SmartFactoryBean &&
    									((SmartFactoryBean<?>) factory).isEagerInit());
    						}
    						if (isEagerInit) {
    							getBean(beanName);
    						}
    					}
    				}
    				else {
                        //普通的bean直接调用getBean()
    					getBean(beanName);
    				}
    			}
    		}
    		//到这里所有的非懒加载的单例Bean已经完成了初始化
    		//......
    	}
    

    接下来就要去到BeanFactory最核心的方法getBean()了。

    #AbstractBeanFactory

    	@Override
    	public Object getBean(String name) throws BeansException {
    		return doGetBean(name, null, null, false);
    	}
    
    	//doGetBean的思想是,初始化过就从容器中拿,否则就进行初始化
    	protected <T> T doGetBean(
    			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    			throws BeansException {
    		//获取beanName,涉及到别名和FactoryBean的情况
    		String beanName = transformedBeanName(name);
            
            //要返回的Bean实例
    		Object beanInstance;
            
    		//从容器中拿bean实例
    		Object sharedInstance = getSingleton(beanName);
            
            //判断容器中拿到的实例是否为空
    		if (sharedInstance != null && args == null) {
    			if (logger.isTraceEnabled()) {
    				if (isSingletonCurrentlyInCreation(beanName)) {
    					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
    							"' that is not fully initialized yet - a consequence of a circular reference");
    				}
    				else {
    					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
    				}
    			}
                //如果是普通Bean就直接返回,
                //是FactoryBean,就返回它创建的那个实例对象
    			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}
    
    		else {
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
    			
                //下面这个if分支,是判断BeanDefinition是否在容器中
                //如果当前容器不存在,就返回父容器的查询结果
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    				String nameToLookup = originalBeanName(name);
    				if (parentBeanFactory instanceof AbstractBeanFactory) {
    					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
    							nameToLookup, requiredType, args, typeCheckOnly);
    				}
    				else if (args != null) {
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				}
    				else if (requiredType != null) {
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    				else {
    					return (T) parentBeanFactory.getBean(nameToLookup);
    				}
    			}
    
    			if (!typeCheckOnly) {
    				markBeanAsCreated(beanName);
    			}
    
                //到这里就要开始创建Bean了,对于singleton的Bean来说,容器还未创建过此Bean,
                //对于prototype来说,就是创建一个新的Bean
    			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
    					.tag("beanName", name);
    			try {
    				if (requiredType != null) {
    					beanCreation.tag("beanType", requiredType::toString);
    				}
    				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				checkMergedBeanDefinition(mbd, beanName, args);
    				
    				//先初始化该Bean所依赖的所有Bean,depends-on
    				String[] dependsOn = mbd.getDependsOn();
    				if (dependsOn != null) {
    					for (String dep : dependsOn) {
                            //检查是否有循环依赖,这里和前面说的循环依赖不是一个概念
    						if (isDependent(beanName, dep)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    						}
                            //注册依赖关系
    						registerDependentBean(dep, beanName);
    						try {
                                //初始化依赖的bean
    							getBean(dep);
    						}
    						catch (NoSuchBeanDefinitionException ex) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
    						}
    					}
    				}
    
    				//单例对象创建
    				if (mbd.isSingleton()) {
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
                                //创建bean的逻辑
    							return createBean(beanName, mbd, args);
    						}
    						catch (BeansException ex) {
    							destroySingleton(beanName);
    							throw ex;
    						}
    					});
    					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
    				//原型对象创建
    				else if (mbd.isPrototype()) {
    					Object prototypeInstance = null;
    					try {
    						beforePrototypeCreation(beanName);
    						//创建bean的逻辑
    						prototypeInstance = createBean(beanName, mbd, args);
    					}
    					finally {
    						afterPrototypeCreation(beanName);
    					}
    					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    				}
    				//如果不是单例或原型的话,需要委托给相应的实现类来处理
    				else {
    					String scopeName = mbd.getScope();
    					if (!StringUtils.hasLength(scopeName)) {
    						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
    					}
    					Scope scope = this.scopes.get(scopeName);
    					if (scope == null) {
    						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    					}
    					try {
    						Object scopedInstance = scope.get(beanName, () -> {
    							beforePrototypeCreation(beanName);
    							try {
                                    //创建bean的逻辑
    								return createBean(beanName, mbd, args);
    							}
    							finally {
    								afterPrototypeCreation(beanName);
    							}
    						});
    						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    					}
    					catch (IllegalStateException ex) {
    						throw new ScopeNotActiveException(beanName, scopeName, ex);
    					}
    				}
    			}
    			catch (BeansException ex) {
    				beanCreation.tag("exception", ex.getClass().toString());
    				beanCreation.tag("message", String.valueOf(ex.getMessage()));
    				cleanupAfterBeanCreationFailure(beanName);
    				throw ex;
    			}
    			finally {
    				beanCreation.end();
    			}
    		}
    		//检查以下类型是否正确,并返回bean对象
    		return adaptBeanInstance(name, beanInstance, requiredType);
    	}
    

    接下来就是分析创建Bean的逻辑,createBean()

    #AbstractAutowireCapableBeanFactory

    	@Override
    	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    			throws BeanCreationException {
    
    		if (logger.isTraceEnabled()) {
    			logger.trace("Creating instance of bean '" + beanName + "'");
    		}
    		RootBeanDefinition mbdToUse = mbd;
            //确保BeanDefinition中的Class被加载
    		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    			mbdToUse = new RootBeanDefinition(mbd);
    			mbdToUse.setBeanClass(resolvedClass);
    		}
    
    		try {
    			mbdToUse.prepareMethodOverrides();
    		}
    		catch (BeanDefinitionValidationException ex) {
    			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    					beanName, "Validation of method overrides failed", ex);
    		}
    
    		try {
                //让 BeanPostProcessors 有机会返回一个代理而不是目标 bean 实例
                //涉及到InstantiationAwareBeanPostProcessor接口
    			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    			if (bean != null) {
    				return bean;
    			}
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
    					"BeanPostProcessor before instantiation of bean failed", ex);
    		}
    
    		try {
                //创建Bean,往里面看
    			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    			if (logger.isTraceEnabled()) {
    				logger.trace("Finished creating instance of bean '" + beanName + "'");
    			}
    			return beanInstance;
    		}
    		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    			throw ex;
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    		}
    	}
    
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    			throws BeanCreationException {
        
    		BeanWrapper instanceWrapper = null;
    		if (mbd.isSingleton()) {
    			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    		}
    		if (instanceWrapper == null) {
                //说明不是FactoryBean,这里实例化Bean
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
        	//返回该包装对象中保存的真正bean实例
    		Object bean = instanceWrapper.getWrappedInstance();
        	//获取bean实例的类型
    		Class<?> beanType = instanceWrapper.getWrappedClass();
    		if (beanType != NullBean.class) {
    			mbd.resolvedTargetType = beanType;
    		}
    
    		//......
    
    		//解决循环依赖,后面篇章再讲解
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    
    		Object exposedObject = bean;
    		try {
                //填充属性,在前面bean只是被实例化,相当于new出来,并没有赋值
    			populateBean(beanName, mbd, instanceWrapper);
                //处理bean初始化后的各种回调
    			exposedObject = initializeBean(beanName, exposedObject, mbd);
    		}
    		catch (Throwable ex) {
    			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    				throw (BeanCreationException) ex;
    			}
    			else {
    				throw new BeanCreationException(
    						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    			}
    		}
    		//......
    		return exposedObject;
    	}
    

    这里重点挑里面的三个方法讲解,创建Bean实例的createBeanInstance()方法,依赖注入的populateBean()方法,初始化后的回调initializeBean()。

    createBeanInstance()

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    		//确保已经加载了该Class
    		Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
        	//校验类的访问权限
    		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    		}
    
    		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    		if (instanceSupplier != null) {
    			return obtainFromSupplier(instanceSupplier, beanName);
    		}
    
    		if (mbd.getFactoryMethodName() != null) {
    			return instantiateUsingFactoryMethod(beanName, mbd, args);
    		}
    		
        	//如果这次不是第一次创建,则可以从第一次创建得知
        	//采用无参构造还是有参构造
    		boolean resolved = false;
    		boolean autowireNecessary = false;
    		if (args == null) {
    			synchronized (mbd.constructorArgumentLock) {
    				if (mbd.resolvedConstructorOrFactoryMethod != null) {
    					resolved = true;
    					autowireNecessary = mbd.constructorArgumentsResolved;
    				}
    			}
    		}
    		if (resolved) {
    			if (autowireNecessary) {
                    //构造依赖注入
    				return autowireConstructor(beanName, mbd, null, null);
    			}
    			else {
                    //无参构造
    				return instantiateBean(beanName, mbd);
    			}
    		}
    
    		//有参构造
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    			return autowireConstructor(beanName, mbd, ctors, args);
    		}
    		ctors = mbd.getPreferredConstructors();
    		if (ctors != null) {
    			return autowireConstructor(beanName, mbd, ctors, null);
    		}
    		//无参构造
    		return instantiateBean(beanName, mbd);
    	}
    

    这里挑无参构造的方法进行查看

    protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
    		try {
    			Object beanInstance;
    			if (System.getSecurityManager() != null) {
    				beanInstance = AccessController.doPrivileged(
    						(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
    						getAccessControlContext());
    			}
    			else {
                    //实例化
    				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
    			}
    			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    			initBeanWrapper(bw);
    			return bw;
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    		}
    	}
    
    	#SimpleInstantiationStrategy
    	@Override
    	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    		if (!bd.hasMethodOverrides()) {
    			Constructor<?> constructorToUse;
    			synchronized (bd.constructorArgumentLock) {
    				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
    				if (constructorToUse == null) {
    					final Class<?> clazz = bd.getBeanClass();
    					if (clazz.isInterface()) {
    						throw new BeanInstantiationException(clazz, "Specified class is an interface");
    					}
    					try {
    						if (System.getSecurityManager() != null) {
    							constructorToUse = AccessController.doPrivileged(
    									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
    						}
    						else {
    							constructorToUse = clazz.getDeclaredConstructor();
    						}
    						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
    					}
    					catch (Throwable ex) {
    						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
    					}
    				}
    			}
                //使用构造方法对象进行反射实例化
    			return BeanUtils.instantiateClass(constructorToUse);
    		}
    		else {
    			return instantiateWithMethodInjection(bd, beanName, owner);
    		}
    	}
    

    populateBean()

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    		//......
    		//获取bean实例的所有属性
    		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    		
        	//获取依赖注入的方式
    		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                    //按名称装配
    				autowireByName(beanName, mbd, bw, newPvs);
    			}
    			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                    //按类型装配
    				autowireByType(beanName, mbd, bw, newPvs);
    			}
    			pvs = newPvs;
    		}
    		//......
    		if (pvs != null) {
                //设置bean实例的属性值
    			applyPropertyValues(beanName, mbd, bw, pvs);
    		}
    	}
    

    initializeBean()

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    				invokeAwareMethods(beanName, bean);
    				return null;
    			}, getAccessControlContext());
    		}
    		else {
                //回调实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的实现类
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
                //BeanPostProcessor的postProcessBeforeInitialization回调
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    
    		try {
                //init-method回调
    			invokeInitMethods(beanName, wrappedBean, mbd);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					(mbd != null ? mbd.getResourceDescription() : null),
    					beanName, "Invocation of init method failed", ex);
    		}
    		if (mbd == null || !mbd.isSynthetic()) {
                //BeanPostProcessor的postProcessAfterInitialization回调
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    		//返回包装Bean实例
    		return wrappedBean;
    	}
    

    到这里,单实例Bean的创建就完成了。

    我们用一张图来梳理一下整体流程

    在这里插入图片描述

    上图包含了容器创建过程和bean的创建过程

    本文仅仅从源码角度分析了IOC容器创建的大体流程,没有去扣细节点,有兴趣的朋友可以自行查看源码,对每个流程的详细情况再做更深的理解。

    展开全文
  • Spring IoC源码分析1

    2022-08-03 14:52:09
    1. bean的装配方式 1.表明当前类是一个配置类,是方法bean的源 2.将@Configuration配置的AppConfig的BeanDefinitio
  • Spring Ioc源码分析系列--@Autowired注解的实现原理.doc
  • Spring Ioc源码分析系列--自动注入循环依赖的处理.doc
  • Spring-IoC源码分析

    2022-05-25 15:11:50
    IoC源码分析 1、IoC定义 将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。 IoC 容器是 Spring⽤来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象 将对象之间的相互...

    Spring-IoC源码分析

    1、IoC定义

    • 将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。
    • IoC 容器是 Spring⽤来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象
    • 将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。
    • IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即
      可,完全不⽤考虑对象是如何被创建出来的。
    • IoC 的实现原理就是工厂模式加反射机制
    • 优点:
      • 代码量降到最低
      • 应用容易测试
      • 最小的代价和最小的侵入性使松散耦合得以实现
      • IOC容器支持加载服务时的饿汉式初始化和懒加载

    2、Spring IoC容器的加载过程

    主流程

    1. new AnnotationConfigApplicationContext实例化化容器入口
    2. 调用本身无参构造函数this()
      1. 会调用父类的无参构造函数创建Bean工厂,然后创建读取注解的Bean定义读取器
      2. 在创建Bean定义读取器时,会注册一些Spring内置的原始Bean定义:
        • ConfigurationClassPostProcessor: 解析我们配置类的处理器
        • AutowiredAnnotationBeanPostProcessor: 处理@Autowired注解的后置处理器
        • RequiredAnnotationBeanPostProcessor:处理@Required属性注解的后置处理器
        • 这些Spring内置的原始Bean定义通过DefaultListableBeanFactory把这些Bean定义放入BeanDefinitionMap(一个ConcurrentHashMap,beanName作为Key,beanDefinition作为Value)中以及beanDefinitionNames(一个List,里面存放了beanName)。
      3. 再创建Bean定义扫描器(仅仅是为了程序员可以手动调用)
    3. 调用register(annotatedClasses);
      1. 会循环传进来的配置类数组执行doRegisterBean方法
      2. 把当前配置类封装成Bean定义
      3. 判断是否需要跳过注解,Spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析
      4. 解析Bean的作用域,如果没有设置的话,默认为单例
      5. 获得BeanName
      6. 解析通用注解,填充到Bean定义中,解析的通用注解:
        • Lazy
        • Primary
        • DependsOn
        • Role
        • Description
      7. 把Bean定义和beanName封装并调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册
      8. 此时只是实例化了一个工厂、把Spring内置的原始Bean定义,还有我们传进来的Bean定义(配置类)注册到BeanDefinitionMap、beanDefinitionNames两个变量中
    4. 调用refresh();
      1. prepareRefresh()刷新前准备工作,主要是保存了容器的启动时间,启动标志等。
      2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 拿到Bean工厂
      3. prepareBeanFactory(beanFactory); 对bean工厂进行填充属性
        • 设置了一个类加载器
        • 设置了bean表达式解析器
        • 设置了一些忽略自动装配的接口
        • 设置了一些允许自动装配的接口,并且进行了赋值操作
        • 注册bean工厂的内部的Bean
      4. invokeBeanFactoryPostProcessors(beanFactory);调用Bean工厂和调用addBeanFactoryPostProcessor添加的Bean工厂后置处理器
      5. registerBeanPostProcessors(beanFactory); 注册和实例化Bean后置处理器。
      6. finishBeanFactoryInitialization(beanFactory);
        • 实例化所有剩余的(非懒加载)单例,比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。
        • 实例化的过程各种BeanPostProcessor开始起作用。

    核心方法分析

    refresh方法的invokeBeanFactoryPostProcessors方法

    • 实际调用的是该方法下的PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法,该方法调用Bean工厂和调用addBeanFactoryPostProcessor添加的Bean工厂后置处理器
    • invokeBeanFactoryPostProcessors方法过程:
      1. 定义了一个Set,装载BeanName,根据这个Set判断后置处理器是否被执行过了
      2. 定义了两个List,一个是regularPostProcessors(装载BeanFactoryPostProcessor,即Bean工程后置处理器),一个是registryProcessors(装载BeanDefinitionRegistryPostProcessor,即Bean定义注册后置处理器)
      3. 循环传进来的postProcessor(后置处理器),只有手动add beanFactoryPostProcessor,这里才会有数据。循环会判断后置处理器是不是Bean定义注册后置处理器,是的话,执行postProcessBeanDefinitionRegistry方法,然后把对象装到registryProcessors里面去,不是的话,就装到regularPostProcessors。
      4. 定义一个List,currentRegistryProcessors保存当前准备执行方法的Bean定义注册后置处理器
      5. 找到类型为BeanDefinitionRegistryPostProcessor的后置处理器名称postProcessorNames。一般情况下,只会找到ConfigurationClassPostProcessor。
      6. 循环postProcessorNames,判断此后置处理器是否实现了PriorityOrdered接口,如果实现了,则调用getBean()的方式获取出该对象然后加入到currentRegistryProcessors集合中去,再放入processedBeans,代表这个后置处理已经被处理过了;(ConfigurationAnnotationProcessor也实现了PriorityOrdered接口)
      7. 进行排序。目前这里只有一个后置处理器,就是ConfigurationClassPostProcessor。
      8. 把保存当前准备执行方法的Bean定义注册后置处理器放入总的registryProcessors中,后续统一执行Bean工厂后置处理器接口中的方法。
      9. 调用currentRegistryProcessors中的Bean定义注册后置处理器实现的postProcessBeanDefinitionRegistry方法。(当前只有ConfigurationClassPostProcessor,此处调用的是当前只有ConfigurationClassPostProcessor实现的postProcessBeanDefinitionRegistry)
      10. 清空currentRegistryProcessors,已经完成了目前的使命,所以需要清空。
      11. 再次找到类型为BeanDefinitionRegistryPostProcessor的后置处理器名称postProcessorNames。
      12. 循环postProcessorNames,判断后置处理器是否被执行过,如果没有被执行过并且实现了Ordered接口,把此后置处理器加入到currentRegistryProcessors和processedBeans中。
      13. 进行排序。
      14. 把保存当前准备执行方法的Bean定义注册后置处理器放入总的registryProcessors中,后续统一执行Bean工厂后置处理器接口中的方法。
      15. 清空currentRegistryProcessors,已经完成了目前的使命,所以需要清空。
      16. 再次找到类型为BeanDefinitionRegistryPostProcessor的后置处理器名称postProcessorNames。
      17. 循环postProcessorNames,判断后置处理器是否被执行过,把此后置处理器加入到currentRegistryProcessors和processedBeans中。此处是把没有实现PriorityOrdered、Ordered的Bean定义注册后置处理器进行执行。
      18. 进行排序。
      19. 把保存当前准备执行方法的Bean定义注册后置处理器放入总的registryProcessors中,后续统一执行Bean工厂后置处理器接口中的方法。
      20. 清空currentRegistryProcessors,已经完成了目前的使命,所以需要清空。
      21. 执行registryProcessors中的Bean定义注册后置处理器的Bean工厂后置处理器方法。
      22. 执行regularPostProcessors中的Bean工厂后置处理器的方法。一般情况下,regularPostProcessors是不会有数据的,只有在外面手动添加BeanFactoryPostProcessor,才会有数据。

    ConfigurationClassPostProcessor实现的postProcessBeanDefinitionRegistry方法

    • 实际调用的是该方法下的processConfigBeanDefinitions方法,该是真正解析Bean定义的方法。
    • ConfigurationClassPostProcessor中的processConfigBeanDefinitions方法十分重要,主要是完成扫描,最终注册我们定义的Bean。
    • processConfigBeanDefinitions方法的过程:
      1. 获得容器中目前所有bean定义的名称放入candidateNames数组。
      2. 循环candidateNames数组,根据beanName获得Bean定义,判断此Bean定义是否解析过。
      3. 如果没有解析过,则调用ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory))进行解析并加入configCandidates候选的配置类集合中
        • 使用@Component @ComponentScan @Import @ImportResource等注解,Spring把这种配置类称之为Lite配置类(非正式的配置类), 如果加了@Configuration注解,就称之为Full配置类(正式配置类)。
      4. 若没有找到配置类 直接返回
      5. 对配置类进行排序
      6. 调用parser.parse(candidates);即ConfigurationClassParser.parse(candidates)方法,真正的解析我们的配置类
      7. 在第6步的时候,只是注册了部分Bean,像 @Bean的方法、@Import 等,是没有被注册的,调用this.reader.loadBeanDefinitions(configClasses);此处才把@Bean的方法和@Import 注册到BeanDefinitionMap中。

    ConfigurationClassParser.parse方法

    1. 在该方法中,因为我们的配置类的BeanDefinition是AnnotatedBeanDefinition的实例,所以会进入第一个if,然后调用processConfigurationClass方法
    2. 在processConfigurationClass方法中重点在于doProcessConfigurationClass方法,真正的进行配置类的解析。

    doProcessConfigurationClass方法

    1. 处理@PropertySource注解,@PropertySource注解用来加载properties文件。
    2. 解析我们的 @ComponentScan 注解,获得ComponentScan注解具体的内容。ComponentScan注解除了最常用的basePackage之外,还有includeFilters,excludeFilters等。
    3. 判断有没有被@ComponentScans标记,或者被@Condition条件带过,如果满足条件的话,进入if
    4. 循环解析ComponentScan注解具体的内容,进行如下操作:
      4.1 ComponentScanAnnotationParser.parse方法执行扫描操作,把扫描出来的Bean定义放入set
      4.2 循环set,判断是否是配置类,是的话,递归调用parse方法,因为被扫描出来的类,还是一个配置类,有@ComponentScans注解,或者其中有被@Bean标记的方法 等等,所以需要再次被解析。
    5. 处理@Import注解,@Import是Spring中很重要的一个注解,正是由于它的存在,让Spring非常灵活,不管是Spring内部,还是与Spring整合的第三方技术,都大量的运用了@Import注解,@Import有三种情况,一种是Import普通类,一种是Import ImportSelector,还有一种是Import ImportBeanDefinitionRegistrar,getImports(sourceClass)是获得import的内容,返回的是一个set。
    6. 处理@ImportResource注解。
    7. 处理@Bean方法,获取到我们配置类中所有标注了@Bean的方法。

    ComponentScanAnnotationParser.parse方法

    1. 定义了一个扫描器scanner。
    2. 处理includeFilters,就是把规则添加到scanner。
    3. 处理excludeFilters,就是把规则添加到scanner。
    4. 解析basePackages,获得需要扫描哪些包。
    5. 添加一个默认的排除规则:排除自身。
    6. scanner.doScan执行扫描
    7. 把传进来的类似命名空间形式的字符串转换成类似类文件地址的形式,然后在前面加上classpath,即:com.xx=>classpath:com/xx/**.class。
    8. 根据packageSearchPath,获得符合要求的文件。
    9. 循环符合要求的文件,进一步进行判断。
    10. 最终会把符合要求的文件,转换为BeanDefinition,并且返回。

    finishBeanFactoryInitialization方法

    1. 实际调用DefaultListableBeanFactory.freezeConfiguration方法,该方法表示注册的 bean 定义将不被修改或任何进一步的处理
    2. 实际调用DefaultListableBeanFactory.preInstantiateSingletons方法实例化剩余的单实例bean

    扫描配置类并将Class注册为Bean定义流程

    1. ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry方法入口
    2. processConfigBeanDefinitions方法ConfigurationClassParser.parser进行解析Bean定义
    3. ConfigurationClassParser.doProcessConfigurationClass真正的解析我们的Bean定义
    4. ComponentScanAnnotationParser.parse方法创建扫描器
    5. ClassPathBeanDefinitionScanner.doScan方法命名空间转换为文件地址进行扫描class类并把注释了@Compent注解的class注册到Bean定义Map中

    Bean定义实例化流程

    1. DefaultListableBeanFactory.preInstantiateSingletons方法入口,循环所有Bean定义
    2. getBean方法下的doGetBean是真正的获取bean的逻辑
    3. createBean方法进入创建bean的逻辑
    4. doCreateBean方法真正的创建我们的bean的实例对象的过程
    5. createBeanInstance方法创建bean实例化
    6. applyMergedBeanDefinitionPostProcessors方法调用合并Bean定义后置处理器(@AutoWired @Value的注解的预解析)
    7. populateBean方法属性赋值
    8. initializeBean进行对象初始化操作
      • applyBeanPostProcessorsBeforeInitialization方法调用Bean后置处理器的postProcessorsBeforeInitialization方法
      • invokeInitMethods方法调用初始化方法
      • applyBeanPostProcessorsAfterInitialization方法调用Bean后置处理器的PostProcessorsAfterInitialization方法

    IoC源码流程总结

    1. 创建应用上下文容器

    2. this方法调用无参构造函数过程:

      1. 调用父类构造函数创建Bean工厂;
      2. 创建读取注解的Bean定义读取器,其中做了如下事情:
        1. 注册一些Spring内置的原始Bean定义(解析我们配置类的处理器、处理@Autowired、@Required注解的后置处理器、处理监听方法的注解@EventListener解析器)到Bean定义Map、BeanNamesList中
      3. 创建Bean定义扫描器(该扫描仅仅是为了提供程序员可以手动调用)
    3. 注册配置类过程:

      1. 将配置类注册到Bean定义Map、BeanNamesList中
    4. 调用refresh方法过程:

      主要是两个方法invokeBeanFactoryPostProcessors调用Bean工厂的后置处理器、finishBeanFactoryInitialization实例化Bean定义Map中未实例化的Bean

      invokeBeanFactoryPostProcessors过程(扫描配置类并将Class注册为Bean定义):

      1. 将Bean定义Map中实现了BeanDefinitionRegistryPostProcessor的类实例化并执行其实现的Bean定义注册后处理方法,此处只会有ConfigurationClassPostProcessor这个类
      2. 调用的是ConfigurationClassPostProcessor下实现的的Bean定义注册后处理方法,在此方法中会解析Bean定义
      3. 获取所有的BeanName并循环获取Bean定义进行解析
      4. 解析配置类上ComponentScans的对象集合属性进行扫描
      5. 循环包路径集合,找到包路径下找到带@Component注解的类注册到Bean定义Map中
      6. 循环上面找到的类,如果是配置类则递归扫描注册

      finishBeanFactoryInitialization过程(Bean实例化流程):

      1. 将Bean定义冻结,不能被修改或任何进一步的处理
      2. 获取所有的BeanName并循环获取尝试获取Bean,如果存在则返回
      3. 创建Bean实例,此时的Bean实例未设置属性不可用
      4. 处理合并Bean定义后置处理器,@AutoWired、@Value注解的预解析
      5. 填充属性,此时依赖注入完成
      6. 调用Bean后置处理器实现的初始化前的方法
      7. 调用初始化方法,如果实现了InitializingBean接口,调用afterPropertiesSet方法;如果定义了init-method方法,则调用init-method方法;
      8. 调用Bean后置处理器实现的初始化后的方法
      9. Bean已经被准备就绪了,一直停留在应用的上下文中

    BeanFactory和FactoryBean的区别

    • BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(IOC容器)来进行管理的。FactoryBean是一个能生产或者修饰对象生成的工厂Bean

    3、Spring 循环依赖问题

    image-20220525101432140

    • 谓的循环依赖是指,A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。或者是 A 依赖 B,B 依赖 C,C 又依赖 A。
    • 主要解决:三级缓存解决
      • singletonObjects 一级缓存(放Object)
      • earlySingletonObjects 二级缓存(放Object)
      • singletonFactories 三级缓存(放ObjectFactory,函数接口实现回调函数)

    主要流程

    image-20220525101630302

    1. 一级缓存中取A对象,如果为空并且不是正在创建状态就加锁成功后再次尝试从一级缓存中获取(此处是为了防止其他线程已经创建完成),如果还是没有则进行创建;
    2. 标记A对象正在创建(放入set中),把A对象完成实例化,此时没有完成初始化;
    3. 往三级缓存中放入一个函数接口(用于其他对象依赖A对象时动态代理生成A对象并注入),此时三级缓存中有A对象;
    4. 对A对象进行属性赋值,发现要注入B对象,然后去获取B对象
    5. 从一级缓存中取B对象,如果为空并且不是正在创建状态就加锁再次尝试从一级缓存中获取(由于此时获取锁为同一线程可重入),如果还是没有则进行创建;
    6. 标记B对象正在创建(放入set中),把A对象完成实例化,此时没有完成初始化;
    7. 往三级缓存中放入一个函数接口(用于其他对象依赖A对象时动态代理生成B对象并注入),此时三级缓存中有A、B对象;
    8. 对B对象进行属性赋值,发现要注入A对象,然后去获取A对象;
    9. 此时一级缓存没有,但是A对象正在创建,然后加锁(此时加锁是为了防止其他线程获取半成品对象)从二级缓存中取,没有就从三级缓存中取回调函数调用动态代理生成对象,取到后放入二级缓存中并从三级缓存中去除,此时二级缓存中有A对象,三级缓存中有B对象;
    10. 然后把A对象注入到B对象,B对象初始化完成,撤销B对象的正在缓存标记,加锁把B放入一级缓存从二三级缓存中去除,此时二级缓存中有A对象,三级缓存中没有对象;
    11. 此时能取到B对象,然后把B对象注入A对象中,A初始化完成,把A放入一级缓存从二三级缓存;
    12. 完成A对象、B对象创建;

    多线程环境下加锁原因

    image-20220525101712194

    • 防止多线程情况下,一个线程在实例化Bean后,未初始化前,其他线程拿到不完成的Bean。

    二级缓存的意义

    • 如果只有一级缓存,那么完整Bean和不完整Bean都放在一级缓存中,并发情况下,有可能取到半成品(未属性赋值、初始化),属性都是null。
    • 二级缓存只要是为了分离完整Bean和不完整Bean(未属性赋值、初始化)的存放, 防止多线程中在Bean还未创建完成时读取到的Bean时不完整的。所以也是为了保证我们getBean是完整最终的Bean,不会出现不完整的情况。

    三级缓存的意义

    为了解耦、方法职责单一、方便后期维护。

    构造函数循环依赖问题

    • Spring没有解决构造函数的循环依赖
    • 解决循环依赖主要是三级缓存的实现(三个Map),在Bean调用构造器实例化之前,三级缓存(三个Map)并没有Bean的任何相关信息,在实例化之后才放入三级缓存中,因此当getBean的时候缓存并没有命中,这样就抛出了循环依赖的异常了。

    多例Bean循环依赖问题

    • 单例Bean:我们是从一级缓存中获取Bean,只需要创建一次对象,后面就可以从缓存中取出来;
    • 多例Bean:每次都要去创建对象,无法利用缓存,就无法解决循环依赖问题;

    4、Spring事件

    Spring事件机制是观察者模式的一种实现,但是除了发布者和监听者者两个角色之外,还有一个EventMultiCaster的角色负责把事件转发给监听者

    image-20220525150149314

    Spring事件组成

    • 事件(ApplicationEvent) 对应于观察者模式中的被观察的事件。
    • 监听器(ApplicationListener) 对应于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生的响应逻辑。
    • 事件发布器(ApplicationEventMulticaster )对应于观察者模式中的被观察者/主题。负责通知观察者对外提供发布事件和增删事件监听器了。

    Spring内置事件

    Event说明
    ContextRefreshedEvent当容器被实例化或refreshed时发布。如调用refresh()方法,此处的实例化是指所有的bean都已被加载,后置处理器都被激活,所有单例bean都已被实例化,所有的容器对象都已准备好可使用。
    ContextStartedEvent当容器启动时发布,即调用start()方法,已启用意味着所有的Lifecycle bean都已显式接收到了start信号。
    ContextStoppedEvent当容器停止时发布,即调用stop()方法,即所有的Lifecycle bean都已显式接收到了stop信号,关闭的容器可以通过start()方法重启
    ContextClosedEvent当容器关闭时发布,即调用close方法。关闭意味着所有的单例bean都已被销毁,关闭的容器不能被重启或refresh。
    自定义事件事件类需要继承ApplicationEvent

    Spring事件机制实现流程

    1. 在创建读取注解的Bean定义读取器时会加载一些Spring原始Bean定义,其中就包括处理监听方法的注解@EventListener解析器;
    2. 在refresh方法中对Bean工厂进行填充属性时会添加一个处理实现了事件监听器接口的探测器后置处理器;
    3. 在refresh方法中创建事件多播器,如果自定义了applicationEventMulticaster 应用多播器组件,会创建自己定义的,否则创建默认的;
      自定义可以设置采用异步方式处理事件,默认采用同步方式处理事件;
    4. 注册实现了实现了事件监听器接口(ApplicationListener)监听器到多播器上,此时把非懒加载的监听器都已经注册,懒加载的监听器会在初始化后注册到多播器;
    5. 在初始化所有的Bean后就会查找所有的Bean标注了@EventListener的方法注册到多播器上。
    展开全文
  • Spring ioc源码分析

    千次阅读 2019-06-19 13:53:12
    Spring源码分析 查看方式 先猜测,后验证,不需要一开始就调试代码 入口 从web.xml入口 DispatcherServlet extends HttpServlet init() :初始化方法(入口) service():浏览器输入url的时候,从web容器调用,doget,...

    Spring源码分析

    核心容器类图

    BeanFactory

    ​ 是典型的工厂模式,为ioc容器开发者管理对象之间的依赖关系提供了很多遍历和基础服务。

    image-20190530105057737

    用的比较多的beanfactory

    FileSystemXmlApplicationContext

    ListableBeanFactory

    接口表示这些 Bean 是可列表化的

    HierarchicalBeanFactory

    这些 Bean 是有继承关系的,也就是每个 Bean 有可能有父 Bean

    AutowireCapableBeanFactory

    定义 Bean 的自动装配规则

    image-20190530105114758

    工厂生产对象

    ​ Spring有很多IOC容器实现。ApplicationContext是Spring提供的一个高级的IOC容器。

    • GenericApplicationContext
    • ClasspathApplicationContext

    通过其接口实现可看出其特点:

    • 支持信息源,可以实现国际化。(实现 MessageSource 接口)
    • 访问资源。(实现 ResourcePatternResolver 接口)
    • 支持应用事件。(实现 ApplicationEventPublisher 接口)

    BeanDefinition

    ​ SpringIOC容器管理了我们定义的各种Bean对象及其相互的关系,Bean对象在Spring中是通过BeanDefinition来描述的

    image-20190530105136091

    BeanDefinitionReader

    用来读取配置文件信息

    image-20190530105257856

    初始化

    定位: 定位配置文件和扫描相关的注解

    加载: 把配置信息载入到内存中

    注册: 根据载入的信息,把对象初始化到IOC容器中

    基于Xml的IOC容器初始化

    ​ IOC容器的初始化包括BeanDefinition的Resource定位,加载和注册这三个基本过程。我们从ApplicationContext为例切入,ApplicationContext系列容器或许使我们最熟悉的,因为Web项目中使用的XmlWebApplicationContext就属于此基础体系,还有ClasspathXmlApplicationContext等,继承体系如下所示:

    image-20190520175809345

    ​ ApplicationContext允许上下文嵌套,通过保持其父上下文可以维持一个上下文体系,对于Bean查找可以在此上下文体系中发生,首先检查上下文,期次是父上下文,逐级向上,这样为不同的Spring应用提供了一个共享额Bean定义环境。

    1、寻找入口

    ​ 有一个我们用的比较多的ClaassPathXmlApplicationContext通过main()方法启动:

    ApplicationContext app =new ClassPathXmlApplicationContext("application.xml");
    

    ​ 先看其构造函数的调用:​

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

    其实际调用的构造函数为

    public ClassPathXmlApplicationContext(
          String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
          throws BeansException {
    
       super(parent);
       setConfigLocations(configLocations);
       if (refresh) {
          refresh();
       }
    }
    

    还有像AnnotationConfigApplicationContextFileSystemXmlApplicationContextXmlWebApplicationContext等都继承自父容器AbstractApplicationContext主要用到了装饰器模式和策略模式,最终都是调用refresh()方法

    2、获得配置路径

    ​ 通过分析ClassPathXmlApplicationContext的源代码可以知道,在创建ClassPathXmlApplicationContext容器时,构造方法做一下两个操作:

    ​ 首先调用父类容器的构造方法为容器设置好Bean资源加载器。

    ​ 然后,调用父类AbstractRefreshableConfigApplicationContextsetConfigLocations(configLocations) 方法设置Bean配置信息的定位路径。

    ​ 通过追踪ClassPathXmlApplicationContext的继承体系,发现其父类的父AbstractApplicationContext中初始化IOC容器所做的主要源码如下:

    public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
      //静态初始化块,在整个容器创建过程中只执行一次 
      static {
        //为了避免应用程序在 Weblogic8.1 关闭时出现类加载异常加载问题,加载 IOC 容器关闭事件(ContextClosedEvent)类 
        ContextClosedEvent.class.getName();
      }
      public AbstractApplicationContext() {
        this.resourcePatternResolver = getResourcePatternResolver();
      }
      public AbstractApplicationContext(@Nullable ApplicationContext parent) { 
        this();
        setParent(parent);
      }
      //获取一个 Spring Source 的加载器用于读入 Spring Bean 配置信息 
      protected ResourcePatternResolver getResourcePatternResolver() {
        //AbstractApplicationContext 继承 DefaultResourceLoader,因此也是一个资源加载器
        //Spring 资源加载器,其 getResource(String location)方法用于载入资源
        return new PathMatchingResourcePatternResolver(this);
      }
    }
    

    AbstractApplicationContext的默认构造方法中有调用PathMatchingResourcePatternResolver的构造方法创建Spring容器资源加载器:

    public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) { 
      Assert.notNull(resourceLoader, "ResourceLoader must not be null"); //设置 Spring 的资源加载器
      this.resourceLoader = resourceLoader;
    }
    

    ​ 在设置容器的资源加载器之后,接下来ClassPathXmlApplicationContext执行setConfigLocation的方法通过调用其父类AbstractRefreshableConfigApplicationContext的方法进行对Bean配置信息的定位,该方法的源码如下

    /**
    * Set the config locations for this application context in init-param style, * i.e. with distinct locations separated by commas, semicolons or whitespace. * <p>If not set, the implementation may use a default as appropriate.
    */
    
    //处理单个资源文件路径为一个字符串的情况
    public void setConfigLocation(String location) {
    
      //String CONFIG_LOCATION_DELIMITERS = ",; /t/n";
      //即多个资源文件路径之间用” ,; \t\n”分隔,解析成数组形式 
      setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
    }
    /**
    * Set the config locations for this application context.
    * <p>If not set, the implementation may use a default as appropriate. */
    //解析 Bean 定义资源文件的路径,处理多个资源文件字符串数组
    public void setConfigLocations(@Nullable 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++) {
          // resolvePath 为同一个类中将字符串解析为路径的方法
          this.configLocations[i] = resolvePath(locations[i]).trim();
        }
      } else {
        this.configLocations = null; }
    }
    

    ​ 通过这两个方法的源码我们可以看出,我们既可以使用一个字符串来配置多个Spring Bean配置信息,也可以使用字符串数组,,即下面两种方式都是可以的:

    ClassPathResouce res=new ClassPathResource("a.xml,b.xml")
    

    多个资源文件路径之间可以用",;\t\n"等分隔

    ClassPathResource res =new ClassPathResource(new String[]{"a.xml","b.xml"});
    

    至此,SpringIOC容器在初始化时将配置的Bean配置信息定位为Spring封装的Resource.

    3、开始启动

    ​ SpringIOC容器对Bean配置资源的载入是从refresh()函数开始的,refresh()是一个模板方法,规定了IOC容器的启动流程,有些逻辑要交给其子类去实现。它对Bean配置资源进行载入ClassPathXmlApplicationContext通过调用其父类AbstractApplicationContextrefresh()函数启动整个IOC容器对Bean定义的载入过程,现在我们来详细看看refresh()中的逻辑处理:

    public abstract class AbstractApplicationContext extends DefaultResourceLoader
    		implements ConfigurableApplicationContext {
    @Override
    public void refresh() throws BeansException, IllegalStateException { 
      synchronized (this.startupShutdownMonitor) {
    
        // Prepare this context for refreshing. 
        //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 
        prepareRefresh();
    
        // Tell the subclass to refresh the internal bean factory. 
        //2、告诉子类启动 refreshBeanFactory()方法,Bean 定义资源文件的载入从子类的 refreshBeanFactory()方法启动
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
        // Prepare the bean factory for use in this context.
        //3、为 BeanFactory 配置容器特性,例如类加载器、事件处理器等 
        prepareBeanFactory(beanFactory);
        try {
    
          // Allows post-processing of the bean factory in context subclasses.
          //4、为容器的某些子类指定特殊的 BeanPost 事件处理器 
          postProcessBeanFactory(beanFactory);
    
          // Invoke factory processors registered as beans in the context. 
          //5、调用所有注册的 BeanFactoryPostProcessor 的 Bean 
          invokeBeanFactoryPostProcessors(beanFactory);
    
          // Register bean processors that intercept bean creation. 
          //6、为 BeanFactory 注册 BeanPost 事件处理器. 
          //BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件 
          registerBeanPostProcessors(beanFactory);
    
          // Initialize message source for this context. 
          //7、初始化信息源,和国际化相关. 
          initMessageSource();
    
          // Initialize event multicaster for this context. 
          //8、初始化容器事件传播器. 
          initApplicationEventMulticaster();
    
          // Initialize other special beans in specific context subclasses.
          //9、调用子类的某些特殊 Bean 初始化方法
          onRefresh();
    
          // Check for listener beans and register them.
          //10、为事件传播器注册事件监听器.
          registerListeners();
    
          // Instantiate all remaining (non-lazy-init) singletons. 
          //11、初始化所有剩余的单例 Bean 
          finishBeanFactoryInitialization(beanFactory);
    
          // Last step: publish corresponding event. 
          //12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件 
          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. 
          //13、销毁已创建的 Bean
          destroyBeans();
    
          // Reset 'active' flag.
          //14、取消 refresh 操作,重置容器的同步标识. 
          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... 
          //15、重设公共缓存
          resetCommonCaches();
        }
      }
    }
    	/**
    	 * Prepare this context for refreshing, setting its startup date and
    	 * active flag as well as performing any initialization of property sources.
    	 */
    	protected void prepareRefresh() {
    		this.startupDate = System.currentTimeMillis();
    		this.closed.set(false);
    		this.active.set(true);
    
    		if (logger.isInfoEnabled()) {
    			logger.info("Refreshing " + this);
    		}
    
    		// Initialize any placeholder property sources in the context environment
    		initPropertySources();
    
    		// Validate that all properties marked as required are resolvable
    		// see ConfigurablePropertyResolver#setRequiredProperties
    		getEnvironment().validateRequiredProperties();
    
    		// Allow for the collection of early ApplicationEvents,
    		// to be published once the multicaster is available...
    		this.earlyApplicationEvents = new LinkedHashSet<>();
    	}
    }
    

    ​ refresh()方法主要为IOC容器Bean的生命周期管理提供条件,Spring IOC容器载入Bean配置信息,从其子类容器的refreshBeanFactory()方法启动,所以整个refresh()

        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    

    这句话之后,代码的都是注册容器的信息源和生命周期时间,我们前面说的载入就是从这句代码开始启动。

    refresh()方法的主要作用是:在注册IOC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保障在refresh之后使用的是新建立起来的IOC容器。它类似于对IOC容器的重启,在新建立好的容器中对容器进行初始化,对Bean配置资源进行载入。

    4、创建容器

    ObtainFreshBeanFactory()方法调用子类容器refreshBeanFactory()方法,启动容器载入Bean配置信息的过程,代码如下:

    public abstract class AbstractApplicationContext extends DefaultResourceLoader
                implements ConfigurableApplicationContext {
    
    	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
          //这里使用了委派设计模式,父类定义了抽象的 refreshBeanFactory()方法,具体实现调用子类容器的 refreshBeanFactory()方法
          refreshBeanFactory();
    
          ConfigurableListableBeanFactory beanFactory = getBeanFactory();
          if (logger.isDebugEnabled()) {
          	logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
          }
          return beanFactory;
       }
    }
    

    AbstractApplicationContext中只抽象定义了refreshBeanFactory()方法,容器真正调用的是其子类AbstractRefreshableApplicationContext实现的refreshBeanFactory()方法,方法的源代码如下

    public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
      /**
    	 * This implementation performs an actual refresh of this context's underlying
    	 * bean factory, shutting down the previous bean factory (if any) and
    	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
    	 */
      @Override
      protected final void refreshBeanFactory() throws BeansException {
        //如果已经有容器,销毁容器中的bean,关闭容器
        if (hasBeanFactory()) {
          destroyBeans();
          closeBeanFactory();
        }
        try {
          //创建IOC容器
          DefaultListableBeanFactory beanFactory = createBeanFactory();
          beanFactory.setSerializationId(getId());
          //对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
          customizeBeanFactory(beanFactory);
          //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
          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 DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(getInternalParentBeanFactory());
      }
      /**
    	 * Customize the internal bean factory used by this context.
    	 * Called for each {@link #refresh()} attempt.
    	 * <p>The default implementation applies this context's
    	 * {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"}
    	 * and {@linkplain #setAllowCircularReferences "allowCircularReferences"} settings,
    	 * if specified. Can be overridden in subclasses to customize any of
    	 * {@link DefaultListableBeanFactory}'s settings.
    	 * @param beanFactory the newly created bean factory for this context
    	 * @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
    	 * @see DefaultListableBeanFactory#setAllowCircularReferences
    	 * @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
    	 * @see DefaultListableBeanFactory#setAllowEagerClassLoading
    	 */
      protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
          beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
          //设置是否允许循环引用
          beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
      }
    }
    

    ​ 在这个方法中,先判断BeanFactory是否存在,如果存在,则先销毁beans并关闭beanFactory,急着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean定义

    5、载入配置路径

    AbstractRefreshableApplicationContext中只定义了抽象的loadBeanDefinitions方法,容器真正调用的是其子类AbstractXmlApplicationContext对该方法的实现,AbstractXmlApplicationContext的主要源码如下:

    public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
      //实现父类抽象的载入Bean定义方法
      @Override
      protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        //创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
        // Configure the bean definition reader with this context's
        // resource loading environment.
        //为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的
        //祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        //为Bean读取器设置SAX xml解析器
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
        initBeanDefinitionReader(beanDefinitionReader);
        //Bean读取器真正实现加载的方法
        loadBeanDefinitions(beanDefinitionReader);
      }
    
      protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
        reader.setValidating(this.validating);
      }
    
      //Xml Bean读取器加载Bean定义资源
      protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        //获取Bean定义资源的定位
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
          //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
          //的Bean定义资源
          reader.loadBeanDefinitions(configResources);
        }
        //如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
          //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
          //的Bean定义资源
          reader.loadBeanDefinitions(configLocations);
        }
      }
      //这里又使用了一个委托模式,调用子类的获取Bean定义资源定位的方法
    	//该方法在ClassPathXmlApplicationContext中进行实现,对于我们
    	//举例分析源码的FileSystemXmlApplicationContext没有使用该方法
    	@Nullable
    	protected Resource[] getConfigResources() {
    		return null;
    	}
    }
    

    ​ 以XmlBean读取器中的一种策略XmlBeanDefinitionReader为例,XmlBeanDefinitionReader调用其父类AbstractBeanDefinitionReaderread.loadBeanDefinition()方法读取Bean配置资源。由于我们使用ClassPathXmlApplicationContext作为例子分析,因为getResources的返回为空,所以程序执行reader.loadBeanDefinition(configLocations)分支。

    6、分配路径处理策略

    ​ 在XmlBeanDefinitionReader的抽象父类AbstractBeanDefinitionReader中定义了载入过程。

    AbstractBeanDefinitionReaderloadBeanDefinitions()方法源码如下:

    public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {
      
      //重载方法,调用loadBeanDefinitions(String);
      @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);
        }
        return counter;
      }
      
      //重载方法,调用下面的loadBeanDefinitions(String, Set<Resource>);方法
      @Override
      public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
        return loadBeanDefinitions(location, null);
      }
      
      public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
        //获取在IoC容器初始化过程中设置的资源加载器
        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 {
            //将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
            //加载多个指定位置的Bean定义资源文件
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            //委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
            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.
          //将指定位置的Bean定义资源文件解析为Spr ing IOC容器封装的资源
          //加载单个指定位置的Bean定义资源文件
          Resource resource = resourceLoader.getResource(location);
          //委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
          int loadCount = loadBeanDefinitions(resource);
          if (actualResources != null) {
            actualResources.add(resource);
          }
          if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
          }
          return loadCount;
        }
      }
    }
    

    AbstractRefreshableConfigApplicationContextloadBeanDefinitions(Resource ... resources)方法实际调用的是AbstractBeanDefinitionReaderloadBeanDefinitions()方法.

    ​ 从对AbstractBeanDefinitionReaderloadBeanDefinitions()方法源码分析可以看出该方法就做了两件事:

    ​ 1.调用资源加载器获取资源方法resourceLoader.getResouce(location),获取到要加载的资源。

    2.真正加载功能的是其子类XmlBeanDefinitionReaderloadBeanDefinitions()方法,在loadBeanDefinition()方法中调用了AbstractApplicationContextgetResouces()方法,跟进去之后发现getResouces()方法其实是定义在ResourcePatternResolver中,此时,我们来查看ResoucePatternResolver的全类图:

    image-20190521212804412

    ​ 从上面可以看到ResouceLoaderApplicationContext的继承关系,可以看出其实际调用的是DefaultResouceLoader中的getSource()方法定位ResouceClassPathXmlApplicationContext本身就是DefaultResouceLoader的实现类

    ,所以此时回到了ClassPathXmlApplicationContext中来。

    ​ 因为在初始化ResourceLoader的时候设置了resourceLoader是自身,所以resourceLoader就是ClassPathXmlApplicationContext

        beanDefinitionReader.setResourceLoader(this);
    

    7、解析配置文件路径

    XmlBeanDefinitionReader通过调用ClassPathXmlApplicationContextDefaultResouceLoadergetResource()方法获取要加载的资源,其源码如下

    public class DefaultResourceLoader implements ResourceLoader {
    
      @Override
      public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
    
        for (ProtocolResolver protocolResolver : this.protocolResolvers) {
          Resource resource = protocolResolver.resolve(location, this);
          if (resource != null) {
            return resource;
          }
        }
        //如果是类路径的方式,那需要使用 ClassPathResource 来得到 bean 文件的资源对象
        if (location.startsWith("/")) {
          return getResourceByPath(location);
        }
        else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
          return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
        }
        else {
          try {
            // 如果是 URL 方式,使用 UrlResource 作为 bean 文件的资源对象
            // Try to parse the location as a URL...
            URL url = new URL(location);
            return new UrlResource(url);
          }
          catch (MalformedURLException ex) {
            //如果既不是 classpath 标识,又不是 URL 标识的 Resource 定位,则调用 //容器本身的 getResourceByPath 方法获取 Resource
            // No URL -> resolve as resource path.
            return getResourceByPath(location);
          }
        }
      }
    }
    

    DefaultResourceLoader提供了getResourceByPath()方法实现,就是为了处理既不是ClassPath标识,又不是URL标识的Resource定位的情况

    protected Resource getResourceByPath(String path) {
      return new ClassPathContextResource(path, getClassLoader());
    }
    

    ​ 在ClassPathResource中完成了对整个路径的解析。这样,就可以从类路径上对IOC配置文件进行加载,当然我们可以按照此逻辑从任何地方加载,在Spring中我们看到他提供的各种资源抽象ClassPathResourceURLRsourceFileSystemResource等来供我们使用。

    ​ 上述我们看到的是定位Resource的一个过程,而这只是加载过程的一部分。FileSystemXmlApplication容器就重写了getResourceByPath()方法:

    @Override
    protected Resource getResourceByPath(String path) { 
      if (path.startsWith("/")) {
        path = path.substring(1); }
      //这里使用文件系统资源对象来定义 bean 文件
      return new FileSystemResource(path);
    }
    

    通过子类的覆盖,巧妙的完成了将类路径转化为文件路径的转化。

    8、开始读取配置内容

    继续回到XmlBeanDefinitionReaderloadBeanDefinitions(Resource ..)方法看到代表bean文件的资源定义以后的载入过程

    public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    
      //XmlBeanDefinitionReader加载资源的入口方法
      @Override
      public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        //将读入的XML资源进行特殊编码处理
        return loadBeanDefinitions(new EncodedResource(resource));
      }
    
      //这里是载入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<>(4);
          this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }
        if (!currentResources.add(encodedResource)) {
          throw new BeanDefinitionStoreException(
            "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        }
        try {
          //将资源文件转为InputStream的IO流
          InputStream inputStream = encodedResource.getResource().getInputStream();
          try {
            //从InputStream中得到XML的解析源
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
              inputSource.setEncoding(encodedResource.getEncoding());
            }
            //这里是具体的读取过程
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
          }
          finally {
            //关闭从Resource中得到的IO流
            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();
          }
        }
      }
      
      	//从特定XML文件中实际载入Bean定义资源的方法
    	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    			throws BeanDefinitionStoreException {
    		try {
    			//将XML文件转换为DOM对象,解析过程由documentLoader实现
    			Document doc = doLoadDocument(inputSource, resource);
    			//这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
    			return registerBeanDefinitions(doc, resource);
    		}
    		catch (BeanDefinitionStoreException ex) {
    			throw ex;
    		}
    		catch (SAXParseException ex) {
    			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
    		}
    		catch (SAXException ex) {
    			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    					"XML document from " + resource + " is invalid", ex);
    		}
    		catch (ParserConfigurationException ex) {
    			throw new BeanDefinitionStoreException(resource.getDescription(),
    					"Parser configuration exception parsing XML from " + resource, ex);
    		}
    		catch (IOException ex) {
    			throw new BeanDefinitionStoreException(resource.getDescription(),
    					"IOException parsing XML document from " + resource, ex);
    		}
    		catch (Throwable ex) {
    			throw new BeanDefinitionStoreException(resource.getDescription(),
    					"Unexpected exception parsing XML document from " + resource, ex);
    		}
    	}
    }
    

    9、准备文档对象

    DocumentLoader把Bean资源转化为Document对象的源码如下:

    public class DefaultDocumentLoader implements DocumentLoader {
    
      //使用标准的JAXP将载入的Bean定义资源转换成document对象
      @Override
      public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
                                   ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
    
        //创建文件解析器工厂
        DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
        if (logger.isDebugEnabled()) {
          logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
        }
        //创建文档解析器
        DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
        //解析Spring的Bean定义资源
        return builder.parse(inputSource);
      }
      
      protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
        throws ParserConfigurationException {
    
        //创建文档解析工厂
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(namespaceAware);
    
        //设置解析XML的校验
        if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
          factory.setValidating(true);
          if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
            // Enforce namespace aware for XSD...
            factory.setNamespaceAware(true);
            try {
              factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
            }
            catch (IllegalArgumentException ex) {
              ParserConfigurationException pcex = new ParserConfigurationException(
                "Unable to validate using XSD: Your JAXP provider [" + factory +
                "] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
                "Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
              pcex.initCause(ex);
              throw pcex;
            }
          }
        }
    
        return factory;
      }
    }
    

    ​ 上述解析过程调用JavaEE标准的JAXP标准进行处理,至此Spring IOC容器根据定位的Bean配置信息,将其加载读入并且转化为Document对象过程完成。接下来我们要继续分析Spring IOC容器如何将载入的Bean配置信息转化为Document对象之后,是如何将其解析为Spring IOC管理的Bean并将其注册到容器中的

    10、分配解析策略

    XmlBeanDefinitionReaderdoLoadBeanDefinitions方法是从特定XMl文件中实际载入Bean配置资源的方法,此方法在载入Bean配置资源之后将其转化为Document对象,之后再registerBeanDefinitions启动Spring IOC容器对Bean定义的解析过程

    public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
      private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
      //创建BeanDefinitionDocumentReader对象,解析Document对象
      protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
        return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
      }
      //按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
      public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        //得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        //获得容器中注册的Bean数量
        int countBefore = getRegistry().getBeanDefinitionCount();
        //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,
        //具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        //统计解析的Bean数量
        return getRegistry().getBeanDefinitionCount() - countBefore;
      }
      /**
    	 * Create the {@link XmlReaderContext} to pass over to the document reader.
    	 */
      public XmlReaderContext createReaderContext(Resource resource) {
        return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
                                    this.sourceExtractor, this, getNamespaceHandlerResolver());
      }
    
      /**
    	 * Lazily create a default NamespaceHandlerResolver, if not set before.
    	 * @see #createDefaultNamespaceHandlerResolver()
    	 */
      public NamespaceHandlerResolver getNamespaceHandlerResolver() {
        if (this.namespaceHandlerResolver == null) {
          this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
        }
        return this.namespaceHandlerResolver;
      }
    
      /**
    	 * Create the default implementation of {@link NamespaceHandlerResolver} used if none is specified.
    	 * Default implementation returns an instance of {@link DefaultNamespaceHandlerResolver}.
    	 */
      protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
        ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
        return new DefaultNamespaceHandlerResolver(cl);
      }
    }
    

    Bean配置资源的载入解析分为以下两个过程:

    ​ 首先通过,调用XML解析器将Bean配置信息转化得到Document对象,但是这些Document对象没有按照SpringBean规则进行解析。这一步是载入的过程。

    ​ 其次在完成通用的XMl解析之后,按照Spring Bean定义的规则对Document对象进行解析,其解析过程是在接口BeandefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader中实现。

    11、将配置载入内存

    XmlBeanDefinitionReader接口通过registerBeanDefinitions方法调用其实现类DefaultBeanDefinitionDocumentReader对Document对象进行解析:

    Spring IOC 容器对载入的 Bean 定义 Document 解析可以看出,我们使用 Spring 时,在 Spring 配置文件中可以使用<import>元素来导入 IOC 容器所需要的其他资源,Spring IOC 容器在解 析时会首先将指定导入的资源加载进容器中。使用<ailas>别名时,Spring IOC 容器首先将别名元素所 定义的别名注册到容器中。

    对于既不是<import>元素,又不是<alias>元素的元素,即 Spring 配置文件中普通的<bean>元素的 解析由 BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement方法来实现。

    public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    
      //按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
      public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        //得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        //获得容器中注册的Bean数量
        int countBefore = getRegistry().getBeanDefinitionCount();
        //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,
        //具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        //统计解析的Bean数量
        return getRegistry().getBeanDefinitionCount() - countBefore;
      }
      	//根据Spring DTD对Bean的定义规则解析Bean定义Document对象
    	@Override
    	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    		//获得XML描述符
    		this.readerContext = readerContext;
    		logger.debug("Loading bean definitions");
    		//获得Document的根元素
    		Element root = doc.getDocumentElement();
    		doRegisterBeanDefinitions(root);
    	}
      	/**
    	 * Create the {@link XmlReaderContext} to pass over to the document reader.
    	 */
    	public XmlReaderContext createReaderContext(Resource resource) {
    		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
    				this.sourceExtractor, this, getNamespaceHandlerResolver());
    	}
    
    	/**
    	 * Lazily create a default NamespaceHandlerResolver, if not set before.
    	 * @see #createDefaultNamespaceHandlerResolver()
    	 */
    	public NamespaceHandlerResolver getNamespaceHandlerResolver() {
    		if (this.namespaceHandlerResolver == null) {
    			this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
    		}
    		return this.namespaceHandlerResolver;
    	}
    
    	/**
    	 * Create the default implementation of {@link NamespaceHandlerResolver} used if none is specified.
    	 * Default implementation returns an instance of {@link DefaultNamespaceHandlerResolver}.
    	 */
    	protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
    		ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
    		return new DefaultNamespaceHandlerResolver(cl);
    	}
    }
    
    
    public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
      /**
    	 * Register each bean definition within the given root {@code <beans/>} element.
    	 */
      protected void doRegisterBeanDefinitions(Element root) {
        //具体的解析过程由BeanDefinitionParserDelegate实现,
        //BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
        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)) {
              if (logger.isInfoEnabled()) {
                logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                            "] not matching: " + getReaderContext().getResource());
              }
              return;
            }
          }
        }
    
        //在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
        preProcessXml(root);
        //从Document的根元素开始进行Bean定义的Document对象
        parseBeanDefinitions(root, this.delegate);
        //在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
        postProcessXml(root);
    
        this.delegate = parent;
      }
    
    

    环境判断

    ​ 首先执行对应Profile标签认证,先取到环境,然后判断环境是否匹配对应的profile,环境获取在

    public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    protected void doRegisterBeanDefinitions(Element root) {
    		//具体的解析过程由BeanDefinitionParserDelegate实现,
    		//BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
    		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)) {
    					if (logger.isInfoEnabled()) {
    						logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
    								"] not matching: " + getReaderContext().getResource());
    					}
    					return;
    				}
    			}
    		}
    
    		//在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
    		preProcessXml(root);
    		//从Document的根元素开始进行Bean定义的Document对象
    		parseBeanDefinitions(root, this.delegate);
    		//在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
    		postProcessXml(root);
    
    		this.delegate = parent;
    	}
    }
    

    getReaderContext().getEnvironment()其实是通过AbstractBeanDefinitionReader获取到的

    在初始化的时候设置了是StandardEnvironment

    public class XmlReaderContext extends ReaderContext {
      public XmlReaderContext(
        Resource resource, ProblemReporter problemReporter,
        ReaderEventListener eventListener, SourceExtractor sourceExtractor,
        XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {
    
        super(resource, problemReporter, eventListener, sourceExtractor);
        this.reader = reader;
        this.namespaceHandlerResolver = namespaceHandlerResolver;
      }
      public final Environment getEnvironment() {
        return this.reader.getEnvironment();
      }
    }
    
    
    

    XmlReaderContextenvironment是从XmlBeanDefinitionReader中获取到的

    public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    
      public XmlReaderContext createReaderContext(Resource resource) {
        return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
                                    this.sourceExtractor, this, getNamespaceHandlerResolver());
      }
    }
    

    XmlBeanDefinitionReaderenvironment是从AbstractBeanDefinitionReader中初始化的

    public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {
    
      protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        this.registry = registry;
    
        // Determine ResourceLoader to use.
        if (this.registry instanceof ResourceLoader) {
          this.resourceLoader = (ResourceLoader) this.registry;
        }
        else {
          this.resourceLoader = new PathMatchingResourcePatternResolver();
        }
    
        // Inherit Environment if possible
        if (this.registry instanceof EnvironmentCapable) {
          this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
        }
        else {
          this.environment = new StandardEnvironment();
        }
      }
    }
    

    image-20190522105645114

    PropertyPlaceholderHelper中记录了对应的读取配置文件的规则,以及解析的方式

    public class PropertyPlaceholderHelper {
    	public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix,
    			@Nullable String valueSeparator, boolean ignoreUnresolvablePlaceholders) {
    
    		Assert.notNull(placeholderPrefix, "'placeholderPrefix' must not be null");
    		Assert.notNull(placeholderSuffix, "'placeholderSuffix' must not be null");
    		this.placeholderPrefix = placeholderPrefix;
    		this.placeholderSuffix = placeholderSuffix;
    		String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix);
    		if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) {
    			this.simplePrefix = simplePrefixForSuffix;
    		}
    		else {
    			this.simplePrefix = this.placeholderPrefix;
    		}
    		this.valueSeparator = valueSeparator;
    		this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
    	}
      protected String parseStringValue(
    			String value, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {
    
    		StringBuilder result = new StringBuilder(value);
    
    		int startIndex = value.indexOf(this.placeholderPrefix);
    		while (startIndex != -1) {
    			int endIndex = findPlaceholderEndIndex(result, startIndex);
    			if (endIndex != -1) {
    				String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
    				String originalPlaceholder = placeholder;
    				if (!visitedPlaceholders.add(originalPlaceholder)) {
    					throw new IllegalArgumentException(
    							"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
    				}
    				// Recursive invocation, parsing placeholders contained in the placeholder key.
    				placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
    				// Now obtain the value for the fully resolved key...
    				String propVal = placeholderResolver.resolvePlaceholder(placeholder);
    				if (propVal == null && this.valueSeparator != null) {
    					int separatorIndex = placeholder.indexOf(this.valueSeparator);
    					if (separatorIndex != -1) {
    						String actualPlaceholder = placeholder.substring(0, separatorIndex);
    						String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
    						propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
    						if (propVal == null) {
    							propVal = defaultValue;
    						}
    					}
    				}
    				if (propVal != null) {
    					// Recursive invocation, parsing placeholders contained in the
    					// previously resolved placeholder value.
    					propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
    					result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
    					if (logger.isTraceEnabled()) {
    						logger.trace("Resolved placeholder '" + placeholder + "'");
    					}
    					startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
    				}
    				else if (this.ignoreUnresolvablePlaceholders) {
    					// Proceed with unprocessed value.
    					startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
    				}
    				else {
    					throw new IllegalArgumentException("Could not resolve placeholder '" +
    							placeholder + "'" + " in value \"" + value + "\"");
    				}
    				visitedPlaceholders.remove(originalPlaceholder);
    			}
    			else {
    				startIndex = -1;
    			}
    		}
    
    		return result.toString();
    	}
    }
    

    元素解析

    解析 <Import> <Alias> <Bean> <Beans>

     public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    
     //创建BeanDefinitionParserDelegate,用于完成真正的解析过程
      protected BeanDefinitionParserDelegate createDelegate(
        XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
    
        BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
        //BeanDefinitionParserDelegate初始化Document根元素
        delegate.initDefaults(root, parentDelegate);
        return delegate;
      }
    
      /**
    	 * Parse the elements at the root level in the document:
    	 * "import", "alias", "bean".
    	 * @param root the DOM root element of the document
    	 */
      //使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象
      protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        //Bean定义的Document对象使用了Spring默认的XML命名空间
        if (delegate.isDefaultNamespace(root)) {
          //获取Bean定义的Document对象根元素的所有子节点
          NodeList nl = root.getChildNodes();
          for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            //获得Document节点是XML元素节点
            if (node instanceof Element) {
              Element ele = (Element) node;
              //Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
              if (delegate.isDefaultNamespace(ele)) {
                //使用Spring的Bean规则解析元素节点
                parseDefaultElement(ele, delegate);
              }
              else {
                //没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点
                delegate.parseCustomElement(ele);
              }
            }
          }
        }
        else {
          //Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的
          //解析规则解析Document根节点
          delegate.parseCustomElement(root);
        }
      }
    
    
      //使用Spring的Bean规则解析Document元素节点
      private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        //如果元素节点是<Import>导入元素,进行导入解析
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
          importBeanDefinitionResource(ele);
        }
        //如果元素节点是<Alias>别名元素,进行别名解析
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
          processAliasRegistration(ele);
        }
        //元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,
        //按照Spring的Bean规则解析元素
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
          processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
          // recurse
          doRegisterBeanDefinitions(ele);
        }
      }
    
    
      /**
    	 * Process the given alias element, registering the alias with the registry.
    	 */
      //解析<Alias>别名元素,为Bean向Spring IoC容器注册别名
      protected void processAliasRegistration(Element ele) {
        //获取<Alias>别名元素中name的属性值
        String name = ele.getAttribute(NAME_ATTRIBUTE);
        //获取<Alias>别名元素中alias的属性值
        String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
        boolean valid = true;
        //<alias>别名元素的name属性值为空
        if (!StringUtils.hasText(name)) {
          getReaderContext().error("Name must not be empty", ele);
          valid = false;
        }
        //<alias>别名元素的alias属性值为空
        if (!StringUtils.hasText(alias)) {
          getReaderContext().error("Alias must not be empty", ele);
          valid = false;
        }
        if (valid) {
          try {
            //向容器的资源读入器注册别名
            getReaderContext().getRegistry().registerAlias(name, alias);
          }
          catch (Exception ex) {
            getReaderContext().error("Failed to register alias '" + alias +
                                     "' for bean with name '" + name + "'", ele, ex);
          }
          //在解析完<Alias>元素之后,发送容器别名处理完成事件
          getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
        }
      }
    
      /**
    	 * Process the given bean element, parsing the bean definition
    	 * and registering it with the registry.
    	 */
      //解析Bean定义资源Document对象的普通元素
      protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
        //对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
        // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
          bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
          try {
            // Register the final decorated instance.
            //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
          }
          catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
          }
          // Send registration event.
          //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
          getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
      }
    }
    }
    

    解析自定义元素

    在上述 delegate.parseCustomElement(root);中,如果我们没有使用spring默认的命名空间即没有使用http://www.springframework.org/schema/beans此命名空间那么会执行此方法

    public class BeanDefinitionParserDelegate {
    
      public BeanDefinition parseCustomElement(Element ele) {
        return parseCustomElement(ele, null);
      }
    
      public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        String namespaceUri = getNamespaceURI(ele);
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
          error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
          return null;
        }
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
      }
    }
    

    上述getNamespaceHandlerResolverDefaultNamespaceHandlerResolver分析解析策略可见得。

    对应resolver方式

    public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver {
      	public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
      
      	public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
    		this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
    	}
    
    	public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) {
    		Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null");
    		this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
    		this.handlerMappingsLocation = handlerMappingsLocation;
    	}
      //匹配对应namespaceUri
      public NamespaceHandler resolve(String namespaceUri) {
        Map<String, Object> handlerMappings = getHandlerMappings();
        Object handlerOrClassName = handlerMappings.get(namespaceUri);
        if (handlerOrClassName == null) {
          return null;
        }
        else if (handlerOrClassName instanceof NamespaceHandler) {
          return (NamespaceHandler) handlerOrClassName;
        }
        else {
          String className = (String) handlerOrClassName;
          try {
            Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
            if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
              throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                                           "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
            }
            //实例化对应handlerclass对象
            NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
            namespaceHandler.init();
            handlerMappings.put(namespaceUri, namespaceHandler);
            return namespaceHandler;
          }
          catch (ClassNotFoundException ex) {
            throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
                                         namespaceUri + "] not found", ex);
          }
          catch (LinkageError err) {
            throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
                                         namespaceUri + "]: problem with handler class file or dependent class", err);
          }
        }
      }
      //加载指定的NamespaceHandler映射。
      private Map<String, Object> getHandlerMappings() {
    		if (this.handlerMappings == null) {
    			synchronized (this) {
    				if (this.handlerMappings == null) {
    					try {
    						Properties mappings =
    								PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
    						if (logger.isDebugEnabled()) {
    							logger.debug("Loaded NamespaceHandler mappings: " + mappings);
    						}
    						Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
    						CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
    						this.handlerMappings = handlerMappings;
    					}
    					catch (IOException ex) {
    						throw new IllegalStateException(
    								"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
    					}
    				}
    			}
    		}
    		return this.handlerMappings;
    	}
    }
    

    从上可知,默认读取META-INF/spring.handlers中的文件例如Spring-Context中的spring.handlers

    http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
    http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
    http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
    http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
    http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
    
    

    NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
    

    可知我们对应解析的类需要实现NamespaceHandler接口

    最后执行对应的init方法和parse方法

    解析<import>

    public class BeanDefinitionParserDelegate {
    
      /**
    	 * Parse an "import" element and load the bean definitions
    	 * from the given resource into the bean factory.
    	 */
      //解析<Import>导入元素,从给定的导入路径加载Bean定义资源到Spring IoC容器中
      protected void importBeanDefinitionResource(Element ele) {
        //获取给定的导入元素的location属性
        String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
        //如果导入元素的location属性值为空,则没有导入任何资源,直接返回
        if (!StringUtils.hasText(location)) {
          getReaderContext().error("Resource location must not be empty", ele);
          return;
        }
    
        // Resolve system properties: e.g. "${user.dir}"
        //使用系统变量值解析location属性值
        location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
    
        Set<Resource> actualResources = new LinkedHashSet<>(4);
    
        // Discover whether the location is an absolute or relative URI
        //标识给定的导入元素的location是否是绝对路径
        boolean absoluteLocation = false;
        try {
          absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
        }
        catch (URISyntaxException ex) {
          // cannot convert to an URI, considering the location relative
          // unless it is the well-known Spring prefix "classpath*:"
          //给定的导入元素的location不是绝对路径
        }
    
        // Absolute or relative?
        //给定的导入元素的location是绝对路径
        if (absoluteLocation) {
          try {
            //使用资源读入器加载给定路径的Bean定义资源
            int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
            if (logger.isDebugEnabled()) {
              logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
            }
          }
          catch (BeanDefinitionStoreException ex) {
            getReaderContext().error(
              "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
          }
        }
        else {
          // No URL -> considering resource location as relative to the current file.
          //给定的导入元素的location是相对路径
          try {
            int importCount;
            //将给定导入元素的location封装为相对路径资源
            Resource relativeResource = getReaderContext().getResource().createRelative(location);
            //封装的相对路径资源存在
            if (relativeResource.exists()) {
              //使用资源读入器加载Bean定义资源
              importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
              actualResources.add(relativeResource);
            }
            //封装的相对路径资源不存在
            else {
              //获取Spring IOC容器资源读入器的基本路径
              String baseLocation = getReaderContext().getResource().getURL().toString();
              //根据Spring IOC容器资源读入器的基本路径加载给定导入路径的资源
              importCount = getReaderContext().getReader().loadBeanDefinitions(
                StringUtils.applyRelativePath(baseLocation, location), actualResources);
            }
            if (logger.isDebugEnabled()) {
              logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
            }
          }
          catch (IOException ex) {
            getReaderContext().error("Failed to resolve current resource location", ele, ex);
          }
          catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
                                     ele, ex);
          }
        }
        Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
        //在解析完<Import>元素之后,发送容器导入其他资源处理完成事件
        getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
      }
    }
    

    解析<Alias>

    	/**
    	 * Process the given alias element, registering the alias with the registry.
    	 */
    	//解析<Alias>别名元素,为Bean向Spring IoC容器注册别名
    	protected void processAliasRegistration(Element ele) {
    		//获取<Alias>别名元素中name的属性值
    		String name = ele.getAttribute(NAME_ATTRIBUTE);
    		//获取<Alias>别名元素中alias的属性值
    		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
    		boolean valid = true;
    		//<alias>别名元素的name属性值为空
    		if (!StringUtils.hasText(name)) {
    			getReaderContext().error("Name must not be empty", ele);
    			valid = false;
    		}
    		//<alias>别名元素的alias属性值为空
    		if (!StringUtils.hasText(alias)) {
    			getReaderContext().error("Alias must not be empty", ele);
    			valid = false;
    		}
    		if (valid) {
    			try {
    				//向容器的资源读入器注册别名
    				getReaderContext().getRegistry().registerAlias(name, alias);
    			}
    			catch (Exception ex) {
    				getReaderContext().error("Failed to register alias '" + alias +
    						"' for bean with name '" + name + "'", ele, ex);
    			}
    			//在解析完<Alias>元素之后,发送容器别名处理完成事件
    			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
    		}
    	}
    
    public class SimpleAliasRegistry implements AliasRegistry {
    
      @Override
      public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        if (alias.equals(name)) {
          this.aliasMap.remove(alias);
        }
        else {
          String registeredName = this.aliasMap.get(alias);
          if (registeredName != null) {
            if (registeredName.equals(name)) {
              // An existing alias - no need to re-register
              return;
            }
            if (!allowAliasOverriding()) {
              throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                                              name + "': It is already registered for name '" + registeredName + "'.");
            }
          }
          checkForAliasCircle(name, alias);
          this.aliasMap.put(alias, name);
        }
      }
    }
    

    解析<Bean>

    Bean 配置信息中的<import><alias>元素解析在 DefaultBeanDefinitionDocumentReader中已
    经完成,对 Bean 配置信息中使用最多的<bean>元素交由BeanDefinitionParserDelegate来解析,

    注册的Beandefinition都注册到了DefalutListAbleFactory

    public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    
      //解析Bean定义资源Document对象的普通元素
      protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
        //对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
        // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
          bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
          try {
            // Register the final decorated instance.
            //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
          }
          catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
          }
          // Send registration event.
          //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
          getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
      }
      	//将解析的BeanDefinitionHold注册到容器中
    	public static void registerBeanDefinition(
    			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    			throws BeanDefinitionStoreException {
    
    		// Register bean definition under primary name.
    		//获取解析的BeanDefinition的名称
    		String beanName = definitionHolder.getBeanName();
    		//向IOC容器注册BeanDefinition
    		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
    		// Register aliases for bean name, if any.
    		//如果解析的BeanDefinition有别名,向容器为其注册别名
    		String[] aliases = definitionHolder.getAliases();
    		if (aliases != null) {
    			for (String alias : aliases) {
    				registry.registerAlias(beanName, alias);
    			}
    		}
    	}
    }
    

    delegate.parseBeanDefinitionElement使用的是BeanDefinitionParserDelegate

    public class BeanDefinitionParserDelegate {
    
      //解析Bean定义资源文件中的<Bean>元素,这个方法中主要处理<Bean>元素的id,name和别名属性
      @Nullable
      public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
        //获取<Bean>元素中的id属性值
        String id = ele.getAttribute(ID_ATTRIBUTE);
        //获取<Bean>元素中的name属性值
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    
        //获取<Bean>元素中的alias属性值
        List<String> aliases = new ArrayList<>();
    
        //将<Bean>元素中的所有name属性值存放到别名中
        if (StringUtils.hasLength(nameAttr)) {
          String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
          aliases.addAll(Arrays.asList(nameArr));
        }
    
        String beanName = id;
        //如果<Bean>元素中没有配置id属性时,将别名中的第一个值赋值给beanName
        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");
          }
        }
    
        //检查<Bean>元素所配置的id或者name的唯一性,containingBean标识<Bean>
        //元素中是否包含子<Bean>元素
        if (containingBean == null) {
          //检查<Bean>元素所配置的id、name或者别名是否重复
          checkNameUniqueness(beanName, aliases, ele);
        }
    
        //详细对<Bean>元素中配置的Bean定义进行解析的地方
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
          if (!StringUtils.hasText(beanName)) {
            try {
              if (containingBean != null) {
                //如果<Bean>元素中没有配置id、别名或者name,且没有包含子元素
                //<Bean>元素,为解析的Bean生成一个唯一beanName并注册
                beanName = BeanDefinitionReaderUtils.generateBeanName(
                  beanDefinition, this.readerContext.getRegistry(), true);
              }
              else {
                //如果<Bean>元素中没有配置id、别名或者name,且包含了子元素
                //<Bean>元素,为解析的Bean使用别名向IOC容器注册
                beanName = this.readerContext.generateBeanName(beanDefinition);
                // Register an alias for the plain bean class name, if still possible,
                // if the generator returned the class name plus a suffix.
                // This is expected for Spring 1.2/2.0 backwards compatibility.
                //为解析的Bean使用别名注册时,为了向后兼容
                //Spring1.2/2.0,给别名添加类名后缀
                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);
          return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }
        //当解析出错时,返回null
        return null;
      }
      //详细对<Bean>元素中配置的Bean定义其他属性进行解析
    	//由于上面的方法中已经对Bean的id、name和别名等属性进行了处理
    	//该方法中主要处理除这三个以外的其他属性数据
    	@Nullable
    	public AbstractBeanDefinition parseBeanDefinitionElement(
    			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    		//记录解析的<Bean>
    		this.parseState.push(new BeanEntry(beanName));
    
    		//这里只读取<Bean>元素中配置的class名字,然后载入到BeanDefinition中去
    		//只是记录配置的class名字,不做实例化,对象的实例化在依赖注入时完成
    		String className = null;
    
    		//如果<Bean>元素中配置了parent属性,则获取parent属性的值
    		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
    			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    		}
    		String parent = null;
    		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
    			parent = ele.getAttribute(PARENT_ATTRIBUTE);
    		}
    
    		try {
    			//根据<Bean>元素配置的class名称和parent属性值创建BeanDefinition
    			//为载入Bean定义信息做准备
    			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    
    			//对当前的<Bean>元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等
    			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    			//为<Bean>元素解析的Bean设置description信息
    			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    
    			//对<Bean>元素的meta(元信息)属性解析
    			parseMetaElements(ele, bd);
    			//对<Bean>元素的lookup-method属性解析
    			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    			//对<Bean>元素的replaced-method属性解析
    			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    
    			//解析<Bean>元素的构造方法设置
    			parseConstructorArgElements(ele, bd);
    			//解析<Bean>元素的<property>设置
    			parsePropertyElements(ele, bd);
    			//解析<Bean>元素的qualifier属性
    			parseQualifierElements(ele, bd);
    
    			//为当前解析的Bean设置所需的资源和依赖对象
    			bd.setResource(this.readerContext.getResource());
    			bd.setSource(extractSource(ele));
    
    			return bd;
    		}
    		catch (ClassNotFoundException ex) {
    			error("Bean class [" + className + "] not found", ele, ex);
    		}
    		catch (NoClassDefFoundError err) {
    			error("Class that bean class [" + className + "] depends on not found", ele, err);
    		}
    		catch (Throwable ex) {
    			error("Unexpected failure during bean definition parsing", ele, ex);
    		}
    		finally {
    			this.parseState.pop();
    		}
    
    		//解析<Bean>元素出错时,返回null
    		return null;
    	}
    }
    

    ​ 在解析<Bean>元素过程中没有创建和实例化Bean对象,只是创建了Bean 对象的定义类
    BeanDefinition,将<Bean>元素中的配置信息设置到BeanDefinition 中作为记录,当依赖注入时才
    使用这些记录信息创建和实例化具体的Bean对象。

    ​ 上面方法中一些对一些配置如元信息(meta)、qualifier 等的解析,我们在 Spring 中配置时使用的也不
    多,我们在使用 Spring 的<Bean>元素时,配置最多的是<property>属性,因此我们下面继续分析源
    码,了解 Bean 的属性在解析时是如何设置的。

    载入<Property>元素

    BeanDefinitionParserDelegate在解析<Bean>调用parsePropertyElements()方法解析<Bean>
    素中的<property>属性子元素,解析源码如下:

    public class BeanDefinitionParserDelegate {
    
      /**
    	 * Parse property sub-elements of the given bean element.
    	 */
      //解析<Bean>元素中的<property>子元素
      public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
        //获取<Bean>元素中所有的子元素
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
          Node node = nl.item(i);
          //如果子元素是<property>子元素,则调用解析<property>子元素方法解析
          if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
            parsePropertyElement((Element) node, bd);
          }
        }
      }
      /**
    	 * Parse a property element.
    	 */
      //解析<property>元素
      public void parsePropertyElement(Element ele, BeanDefinition bd) {
        //获取<property>元素的名字
        String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
        if (!StringUtils.hasLength(propertyName)) {
          error("Tag 'property' must have a 'name' attribute", ele);
          return;
        }
        this.parseState.push(new PropertyEntry(propertyName));
        try {
          //如果一个Bean中已经有同名的property存在,则不进行解析,直接返回。
          //即如果在同一个Bean中配置同名的property,则只有第一个起作用
          if (bd.getPropertyValues().contains(propertyName)) {
            error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
            return;
          }
          //解析获取property的值
          Object val = parsePropertyValue(ele, bd, propertyName);
          //根据property的名字和值创建property实例
          PropertyValue pv = new PropertyValue(propertyName, val);
          //解析<property>元素中的属性
          parseMetaElements(ele, pv);
          pv.setSource(extractSource(ele));
          bd.getPropertyValues().addPropertyValue(pv);
        }
        finally {
          this.parseState.pop();
        }
      }
      //解析获取property值
      @Nullable
      public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
        String elementName = (propertyName != null) ?
          "<property> element for property '" + propertyName + "'" :
        "<constructor-arg> element";
    
        // Should only have one child element: ref, value, list, etc.
        //获取<property>的所有子元素,只能是其中一种类型:ref,value,list,etc等
        NodeList nl = ele.getChildNodes();
        Element subElement = null;
        for (int i = 0; i < nl.getLength(); i++) {
          Node node = nl.item(i);
          //子元素不是description和meta属性
          if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
              !nodeNameEquals(node, META_ELEMENT)) {
            // Child element is what we're looking for.
            if (subElement != null) {
              error(elementName + " must not contain more than one sub-element", ele);
            }
            else {
              //当前<property>元素包含有子元素
              subElement = (Element) node;
            }
          }
        }
    
        //判断property的属性值是ref还是value,不允许既是ref又是value
        boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
        boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
        if ((hasRefAttribute && hasValueAttribute) ||
            ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
          error(elementName +
                " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
        }
    
        //如果属性是ref,创建一个ref的数据对象RuntimeBeanReference
        //这个对象封装了ref信息
        if (hasRefAttribute) {
          String refName = ele.getAttribute(REF_ATTRIBUTE);
          if (!StringUtils.hasText(refName)) {
            error(elementName + " contains empty 'ref' attribute", ele);
          }
          //一个指向运行时所依赖对象的引用
          RuntimeBeanReference ref = new RuntimeBeanReference(refName);
          //设置这个ref的数据对象是被当前的property对象所引用
          ref.setSource(extractSource(ele));
          return ref;
        }
        //如果属性是value,创建一个value的数据对象TypedStringValue
        //这个对象封装了value信息
        else if (hasValueAttribute) {
          //一个持有String类型值的对象
          TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
          //设置这个value数据对象是被当前的property对象所引用
          valueHolder.setSource(extractSource(ele));
          return valueHolder;
        }
        //如果当前<property>元素还有子元素
        else if (subElement != null) {
          //解析<property>的子元素
          return parsePropertySubElement(subElement, bd);
        }
        else {
          // Neither child element nor "ref" or "value" attribute found.
          //propery属性中既不是ref,也不是value属性,解析出错返回null
          error(elementName + " must specify a ref or value", ele);
          return null;
        }
      }
    
    }
    

    通过上述分析,我们可以了解在Spring配置文件中,<Bean>元素中<property>元素的相关配置是如何处理的:

    1、ref被封装为指向依赖对象的一个引用

    2、value配置都会封装成一个字符串类型的对象

    3、ref和value都通过TypedStringValue.setSource(extractSource(ele));方法将属性值/引用
    与所引用的属性关联起来。

    此方法的最后对于<Property>元素的子元素通过parsePropertySubElement()方法解析,我们继续分析此方法的源码,了解其解析过程

    载入<Property>子元素

    BeanDefinitionParserDelegate类中的 parsePropertySubElement()方法对<property>中的子元
    素解析,源码如下

    public class BeanDefinitionParserDelegate {
      @Nullable
      public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
        return parsePropertySubElement(ele, bd, null);
      }
      //解析<property>元素中ref,value或者集合等子元素
      @Nullable
      public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
        //如果<property>没有使用Spring默认的命名空间,则使用用户自定义的规则解析内嵌元素
        if (!isDefaultNamespace(ele)) {
          return parseNestedCustomElement(ele, bd);
        }
        //如果子元素是bean,则使用解析<Bean>元素的方法解析
        else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
          BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
          if (nestedBd != null) {
            nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
          }
          return nestedBd;
        }
        //如果子元素是ref,ref中只能有以下3个属性:bean、local、parent
        else if (nodeNameEquals(ele, REF_ELEMENT)) {
          // A generic reference to any name of any bean.
          //可以不再同一个Spring配置文件中,具体请参考Spring对ref的配置规则
          String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
          boolean toParent = false;
          if (!StringUtils.hasLength(refName)) {
            // A reference to the id of another bean in a parent context.
            //获取<property>元素中parent属性值,引用父级容器中的Bean
            refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
            toParent = true;
            if (!StringUtils.hasLength(refName)) {
              error("'bean' or 'parent' is required for <ref> element", ele);
              return null;
            }
          }
          if (!StringUtils.hasText(refName)) {
            error("<ref> element contains empty target attribute", ele);
            return null;
          }
          //创建ref类型数据,指向被引用的对象
          RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
          //设置引用类型值是被当前子元素所引用
          ref.setSource(extractSource(ele));
          return ref;
        }
        //如果子元素是<idref>,使用解析ref元素的方法解析
        else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
          return parseIdRefElement(ele);
        }
        //如果子元素是<value>,使用解析value元素的方法解析
        else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
          return parseValueElement(ele, defaultValueType);
        }
        //如果子元素是null,为<property>设置一个封装null值的字符串数据
        else if (nodeNameEquals(ele, NULL_ELEMENT)) {
          // It's a distinguished null value. Let's wrap it in a TypedStringValue
          // object in order to preserve the source location.
          TypedStringValue nullHolder = new TypedStringValue(null);
          nullHolder.setSource(extractSource(ele));
          return nullHolder;
        }
        //如果子元素是<array>,使用解析array集合子元素的方法解析
        else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
          return parseArrayElement(ele, bd);
        }
        //如果子元素是<list>,使用解析list集合子元素的方法解析
        else if (nodeNameEquals(ele, LIST_ELEMENT)) {
          return parseListElement(ele, bd);
        }
        //如果子元素是<set>,使用解析set集合子元素的方法解析
        else if (nodeNameEquals(ele, SET_ELEMENT)) {
          return parseSetElement(ele, bd);
        }
        //如果子元素是<map>,使用解析map集合子元素的方法解析
        else if (nodeNameEquals(ele, MAP_ELEMENT)) {
          return parseMapElement(ele, bd);
        }
        //如果子元素是<props>,使用解析props集合子元素的方法解析
        else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
          return parsePropsElement(ele);
        }
        //既不是ref,又不是value,也不是集合,则子元素配置错误,返回null
        else {
          error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
          return null;
        }
      }
    }
    

    ​ 通过上述源码分析,我们明白了在 Spring 配置文件中,对<property>元素中配置的 arraylistsetmapprop 等各种集合子元素的都通过上述方法解析,生成对应的数据对象,比如 ManagedListManagedArrayManagedSet 等,这些 Managed 类是 Spring 对象 BeanDefiniton 的数据封装,对集合数据类型的具体解析有各自的解析方法实现,解析方法的命名非常规范,一目了然,我们对<list>集合元素的解析方法进行源码分析,了解其实现过程。

    载入<list>的子元素
    public class BeanDefinitionParserDelegate {
    
      /**
    	 * Parse a list element.
    	 */
      //解析<list>集合子元素
      public List<Object> parseListElement(Element collectionEle, @Nullable BeanDefinition bd) {
        //获取<list>元素中的value-type属性,即获取集合元素的数据类型
        String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
        //获取<list>集合元素中的所有子节点
        NodeList nl = collectionEle.getChildNodes();
        //Spring中将List封装为ManagedList
        ManagedList<Object> target = new ManagedList<>(nl.getLength());
        target.setSource(extractSource(collectionEle));
        //设置集合目标数据类型
        target.setElementTypeName(defaultElementType);
        target.setMergeEnabled(parseMergeAttribute(collectionEle));
        //具体的<list>元素解析
        parseCollectionElements(nl, target, bd, defaultElementType);
        return target;
      }
      //具体解析<list>集合元素,<array>、<list>和<set>都使用该方法解析
      protected void parseCollectionElements(
        NodeList elementNodes, Collection<Object> target, @Nullable BeanDefinition bd, String defaultElementType) {
        //遍历集合所有节点
        for (int i = 0; i < elementNodes.getLength(); i++) {
          Node node = elementNodes.item(i);
          //节点不是description节点
          if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
            //将解析的元素加入集合中,递归调用下一个子元素
            target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
          }
        }
      }
    }
    
    

    解析<Beans>

    如果是Beans则重新调用对应的doRegisterBeanDefinitions方法

    public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    			doRegisterBeanDefinitions(ele);
    }
    

    ​ 经过对 Spring Bean 配置信息转换的 Document 对象中的元素层层解析,Spring IOC 现在已经将 XML 形式定义的 Bean 配置信息转换为 Spring IOC 所识别的数据结构——BeanDefinition,它是 Bean 配 置信息中配置的 POJO 对象在 Spring IOC 容器中的映射,我们可以通过 AbstractBeanDefinition 为 入口,看到了 IOC 容器进行索引、查询和操作。

    ​ 通过 Spring IOC 容器对 Bean 配置资源的解析后,IOC 容器大致完成了管理 Bean 对象的准备工作, 即初始化过程,但是最为重要的依赖注入还没有发生,现在在 IOC 容器中 BeanDefinition 存储的只是 一些静态信息,接下来需要向容器注册 Bean 定义信息才能全部完成 IOC 容器的初始化过程

    12、分配注册策略

    ​ 让我们继续跟踪程序的执行顺序,接下来我们来分析 DefaultBeanDefinitionDocumentReader 对 Bean 定义转换的 Document 对象解析的流程中,在其 parseDefaultElement()方法中完成对 Document 对象的解析后得到封装 BeanDefinitionBeanDefinitionHold 对象,然后调用 BeanDefinitionReaderUtilsregisterBeanDefinition()方法向 IOC 容 器 注 册 解 析 的 Bean ,
    BeanDefinitionReaderUtils 的注册的源码如下:

    public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    
      //解析Bean定义资源Document对象的普通元素
      protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
        //对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
        // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
          bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
          try {
            // Register the final decorated instance.
            //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
          }
          catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
          }
          // Send registration event.
          //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
          getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
      }
    }
    

    ​ 调用BeanDefinitionReaderUtils想IOC容器注册解析的BeanDefinition时,真正完成注册功能的是DefaultListableBeanFactory

    13、向容器注册

    DefaultListableBeanFactory 中使用一个 HashMap 的集合对象存放 IOC 容器中注册解析的BeanDefinition,向 IOC 容器注册的主要源码如下:

    image-20190522135853148

    @SuppressWarnings("serial")
    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    
    /** Map of bean definition objects, keyed by bean name */
    	//存储注册信息的BeanDefinition
    	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    //向IOC容器注册解析的BeanDefiniton
    	@Override
    	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    			throws BeanDefinitionStoreException {
    
    Assert.hasText(beanName, "Bean name must not be empty");
    	Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
    	//校验解析的BeanDefiniton
    	if (beanDefinition instanceof AbstractBeanDefinition) {
    		try {
    			((AbstractBeanDefinition) beanDefinition).validate();
    		}
    		catch (BeanDefinitionValidationException ex) {
    			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    					"Validation of bean definition failed", ex);
    		}
    	}
    
    	BeanDefinition oldBeanDefinition;
    
    	oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    
    	if (oldBeanDefinition != null) {
    		if (!isAllowBeanDefinitionOverriding()) {
    			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    					"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
    					"': There is already [" + oldBeanDefinition + "] bound.");
    		}
    		else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
    			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    			if (this.logger.isWarnEnabled()) {
    				this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
    						"' with a framework-generated bean definition: replacing [" +
    						oldBeanDefinition + "] with [" + beanDefinition + "]");
    			}
    		}
    		else if (!beanDefinition.equals(oldBeanDefinition)) {
    			if (this.logger.isInfoEnabled()) {
    				this.logger.info("Overriding bean definition for bean '" + beanName +
    						"' with a different definition: replacing [" + oldBeanDefinition +
    						"] with [" + beanDefinition + "]");
    			}
    		}
    		else {
    			if (this.logger.isDebugEnabled()) {
    				this.logger.debug("Overriding bean definition for bean '" + beanName +
    						"' with an equivalent definition: replacing [" + oldBeanDefinition +
    						"] with [" + beanDefinition + "]");
    			}
    		}
    		this.beanDefinitionMap.put(beanName, beanDefinition);
    	}
    	else {
    		if (hasBeanCreationStarted()) {
    			// Cannot modify startup-time collection elements anymore (for stable iteration)
    			//注册的过程中需要线程同步,以保证数据的一致性
    			synchronized (this.beanDefinitionMap) {
    				this.beanDefinitionMap.put(beanName, beanDefinition);
    				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
    				updatedDefinitions.addAll(this.beanDefinitionNames);
    				updatedDefinitions.add(beanName);
    				this.beanDefinitionNames = updatedDefinitions;
    				if (this.manualSingletonNames.contains(beanName)) {
    					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
    					updatedSingletons.remove(beanName);
    					this.manualSingletonNames = updatedSingletons;
    				}
    			}
    		}
    		else {
    			// Still in startup registration phase
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    			this.beanDefinitionNames.add(beanName);
    			this.manualSingletonNames.remove(beanName);
    		}
    		this.frozenBeanDefinitionNames = null;
    	}
    
    	//检查是否有同名的BeanDefinition已经在IOC容器中注册
    	if (oldBeanDefinition != null || containsSingleton(beanName)) {
    		//重置所有已经注册过的BeanDefinition的缓存
    		resetBeanDefinition(beanName);
    	}
    }
    

    ​ 至此,Bean 配置信息中配置的 Bean 被解析过后,已经注册到 IOC 容器中,被容器管理起来,真正完成了 IOC 容器初始化所做的全部工作。现在 IOC 容器中已经建立了整个 Bean 的配置信息,这些BeanDefinition 信息已经可以使用,并且可以被检索,IOC 容器的作用就是对这些注册的 Bean 定义信息进行处理和维护。这些注册的 Bean 定义信息是 IOC 容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。

    基于Annotation的IOC初始化

    Annotation的前世今生

    ​ 从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是jdk1.5中引入的一个新特性,用于简化Bean的配置,可以取代XMl配置文件。开发人员对注解(Annotation)的态度也是萝卜白菜各有所爱,个人认为注解可以大大简化配置,提高开发速度,但也给后期维护增加了难度。目前来说Xml方式的发展相对成熟,方便于统一管理。随着SpringBoot的兴起,基于注解的开发甚至实现了零配置。但作为个人的习惯而言,还是倾向于XML配置文件和注解(Annotation)相互配合使用。Spring IOC容器对于累计别的注解和类内部的注解分为以下两种策略:

    1. 类级别的注解:@Component,@Repository,@Controller,Service以及JAVAEE6的@ManagedBean@Named注解,都是天价在类上面的类级别注解,Spring容器根据注解的规则扫描读取注解Bean定义类,并将其注册到SPring IOC容器中
    2. 类内部的注解:如Autowire@Value@Resource及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解,Spring IOC容器通过Bean后置注解处理器解析Bean内部的注解,下面通过这两种处理策略,分别分析Spring处理注解相关的源码。

    定位Bean扫描路径

    ​ 在Spring中管理注解Bean定义的容器由两个:AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext。这两个类时专门处理Spring注解方式配置的容器,直接依赖于注解作为容器配置信息来源的IOC容器。AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext的Web版本,两者的用法以及对注解的处理方式几乎没有差别。

    ​ 如果我们在xml中这样配置那么会使用 AnnotationConfigApplicationContext,可以参考对应将配置载入内存中的解析自定义元素

    通过xml去配置解析annotation

    <?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
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
    	xmlns:context="http://www.springframework.org/schema/context">
    
    	<context:annotation-config/>
    </beans?:L. 432
    
      87
    

    上述使用 <context:annotation-config/>读取对应handler使用的是:org.springframework.context.config.ContextNamespaceHandler

    在对应的

    注册xml解析器

    public class ContextNamespaceHandler extends NamespaceHandlerSupport {
    
      @Override
      public void init() {
        registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
        registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
        registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
        registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
        registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
      }
    }
    

    中定义解析annotation-config的是AnnotationConfigBeanDefinitionParser

    所以我们查看AnnotationConfigBeanDefinitionParserparser方法

    public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {
    
      @Override
      public BeanDefinition parse(Element element, ParserContext parserContext) {
        Object source = parserContext.extractSource(element);
    
        // Obtain bean definitions for all relevant BeanPostProcessors.
        //获取所有相关BeanPostProcessors的bean定义。
        Set<BeanDefinitionHolder> processorDefinitions =
          AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
    
        // Register component for the surrounding <context:annotation-config> element.
        CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
        parserContext.pushContainingComponent(compDefinition);
    
        // Nest the concrete beans in the surrounding component.
        for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
          parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
        }
    
        // Finally register the composite component.
        parserContext.popAndRegisterContainingComponent();
    
        return null;
      }
    }
    

    在其中

    声明Processor

    public class AnnotationConfigUtils {
    
      public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, Object source) {
    
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
          if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
          }
          if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
          }
        }
    
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
    
        //增加 ConfigurationClassPostProcessor
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
          RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
          def.setSource(source);
          beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
    
        //增加 AutowiredAnnotationBeanPostProcessor
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
          RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
          def.setSource(source);
          beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
    
        //增加RequiredAnnotationBeanPostProcessor
        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
          RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
          def.setSource(source);
          beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
    
        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
          RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
          def.setSource(source);
          beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
    
        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
          RootBeanDefinition def = new RootBeanDefinition();
          try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                                AnnotationConfigUtils.class.getClassLoader()));
          }
          catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
              "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
          }
          def.setSource(source);
          beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
    
        //增加EventListenerMethodProcessor
        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
          RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
          def.setSource(source);
          beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }
        //增加
        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
          RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
          def.setSource(source);
          beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }
    
        return beanDefs;
      }
    }
    

    在上述默认增加了

    AutowiredAnnotationBeanPostProcessor

    ​ 作用: 使用@autowired

    ``CommonAnnotationBeanPostProcessor`

    ​ 作用: 使用@Resource @PostConstruct @PreDestroy

    PersistenceAnnotationBeanPostProcessor

    ​ 作用: 使用@PersistenceContext

    RequiredAnnotationBeanPostProcessor

    ​ 作用: 使用@Required

    如果我们使用<Component-scan/>就可以不适用<context:annotation-config/>

    image-20190524121205021

    因为其都调用了AnnotationConfigUtilsregisterAnnotationConfigProcessors方法

    直接使用AnnotationConfigApplicationContext

    现在通过AnnotationConfigApplicationContext为例查看其源码

    public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
    
    	//保存一个读取注解的Bean定义读取器,并将其设置到容器中
    	private final AnnotatedBeanDefinitionReader reader;
    
    	//保存一个扫描指定类路径中注解Bean定义的扫描器,并将其设置到容器中
    	private final ClassPathBeanDefinitionScanner scanner;
    
    	//默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()
    	//方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean的载入、解析和注册过程
    	public AnnotationConfigApplicationContext() {
    		this.reader = new AnnotatedBeanDefinitionReader(this);
    		this.scanner = new ClassPathBeanDefinitionScanner(this);
    	}
    
    	/**
    	 * Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
    	 * @param beanFactory the DefaultListableBeanFactory instance to use for this context
    	 */
    	public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
    		super(beanFactory);
    		this.reader = new AnnotatedBeanDefinitionReader(this);
    		this.scanner = new ClassPathBeanDefinitionScanner(this);
    	}
    
    	/**
    	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
    	 * from the given annotated classes and automatically refreshing the context.
    	 * @param annotatedClasses one or more annotated classes,
    	 * e.g. {@link Configuration @Configuration} classes
    	 */
    	//最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的Bean自动注册到容器中
    	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    		this();
    		register(annotatedClasses);
    		refresh();
    	}
    
    	/**
    	 * Create a new AnnotationConfigApplicationContext, scanning for bean definitions
    	 * in the given packages and automatically refreshing the context.
    	 * @param basePackages the packages to check for annotated classes
    	 */
    	//该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中
    	public AnnotationConfigApplicationContext(String... basePackages) {
    		this();
    		scan(basePackages);
    		refresh();
    	}
    
    
    	/**
    	 * {@inheritDoc}
    	 * <p>Delegates given environment to underlying {@link AnnotatedBeanDefinitionReader}
    	 * and {@link ClassPathBeanDefinitionScanner} members.
    	 */
    	@Override
    	public void setEnvironment(ConfigurableEnvironment environment) {
    		super.setEnvironment(environment);
    		this.reader.setEnvironment(environment);
    		this.scanner.setEnvironment(environment);
    	}
    
    	//为容器的注解Bean读取器和注解Bean扫描器设置Bean名称产生器
    	public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
    		this.reader.setBeanNameGenerator(beanNameGenerator);
    		this.scanner.setBeanNameGenerator(beanNameGenerator);
    		getBeanFactory().registerSingleton(
    				AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
    	}
    
    
    	//为容器的注解Bean读取器和注解Bean扫描器设置作用范围元信息解析器
    	public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
    		this.reader.setScopeMetadataResolver(scopeMetadataResolver);
    		this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
    	}
    
    	//为容器注册一个要被处理的注解Bean,新注册的Bean,必须手动调用容器的
    	//refresh()方法刷新容器,触发容器对新注册的Bean的处理
    	public void register(Class<?>... annotatedClasses) {
    		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
    		this.reader.register(annotatedClasses);
    	}
    
    
    	//扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用
    	//refresh()方法刷新容器
    	public void scan(String... basePackages) {
    		Assert.notEmpty(basePackages, "At least one base package must be specified");
    		this.scanner.scan(basePackages);
    	}
    }
    
    

    ​ 通过上述源码分析,我们可以看到Spring对注解的处理分成两种方式:

    1. 直接把注册Bean注册到容器中

      ​ 可以在初始化容器时注册,也可以在容器创建之后手动调用注册方法像容器注册,然后通过手动刷新容器,是的容器对注册的注解Bean进行处理

    2. 通过扫描指定的包以及其子包下的所有类

      ​ 在初始化注册容器式指定要自动扫描的路径,如果容器创建以后向给定路径动态的添加了注解Bean,则需要手动调用容器扫描的方法,然后手动刷新容器,使得容器对所注册的Bean进行处理。

    接下来,对两种方式详细分析其具体实现过程

    读取Annotation元数据

    ​ 当创建构建注解处理容器时,如果传入的初始参数是具体的注解Bean定义类时,注解容器读取并注册。

    AnnotationConfigApplicationContext通过调用注解Bean定义读取器

    AnnotatedBeanDefinitionReaderregister()方法向容器注册指定的注解Bean,注解Bean定义读取器想容器注册Bean的源码如下:

    public class AnnotatedBeanDefinitionReader {
    
      //注册多个注解Bean定义类
      public void register(Class<?>... annotatedClasses) {
        for (Class<?> annotatedClass : annotatedClasses) {
          registerBean(annotatedClass);
        }
      }
    
    
      //注册一个注解Bean定义类
      public void registerBean(Class<?> annotatedClass) {
        doRegisterBean(annotatedClass, null, null, null);
      }
    
    
      public <T> void registerBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier) {
        doRegisterBean(annotatedClass, instanceSupplier, null, null);
      }
      //Bean定义读取器向容器注册注解Bean定义类
    	<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
    			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
    
    		//根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构
    		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
    		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
    			return;
    		}
    
    		abd.setInstanceSupplier(instanceSupplier);
    		//解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;
    		//若@Scope("singleton"),则Bean为单态类型
    		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    		//为注解Bean定义设置作用域
    		abd.setScope(scopeMetadata.getScopeName());
    		//为注解Bean定义生成Bean名称
    		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    
    		//处理注解Bean定义中的通用注解
    		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    		//如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
    		//主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
    		//Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
    		if (qualifiers != null) {
    			for (Class<? extends Annotation> qualifier : qualifiers) {
    				//如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
    				if (Primary.class == qualifier) {
    					abd.setPrimary(true);
    				}
    				//如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
    				//则该Bean为预实例化
    				else if (Lazy.class == qualifier) {
    					abd.setLazyInit(true);
    				}
    				//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
    				//个autowiring自动依赖注入装配限定符,该Bean在进autowiring
    				//自动依赖注入装配时,根据名称装配限定符指定的Bean
    				else {
    					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
    				}
    			}
    		}
    		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
    			customizer.customize(abd);
    		}
    
    		//创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
    		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    		//根据注解Bean定义类中配置的作用域,创建相应的代理对象
    		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    		//向IOC容器注册注解Bean类定义对象
    		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    	}
    
    }
    

    ​ 从上述的源码可以看出,注册注解Bean定义类的基本步骤:

    • 需要使用注解元数据解析器AnnotationScopeMetadataResolverresolveScopeMetadata(BeanDefinition definition)解析注解Bean中关于作用域的配置
    • 使用AnnotationConfigUtilsprocessCommonDefinitionAnnotions()方法处理注解Bean定义类中通用的注解
    • 使用AnnotationConfigUtilsapplyScopedProxyMode()方法创建对于作用域的代理对象
    • 通过BeanDefinitionReaderUtils像容器注册Bean

    接下来按照此步骤进行分析

    AnnotationScopeMetadataResolver解析作用域元数据

    AnnotationScopeMetadataResolverresolveScopeMetadata(BeanDefinition definition)解析注解Bean定义类的作用域原信息,即判断注册的Bean是原生类型prototype还是单例singleton类型

    public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
    
      //解析注解Bean定义类中的作用域元信息
      @Override
      public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
        ScopeMetadata metadata = new ScopeMetadata();
        if (definition instanceof AnnotatedBeanDefinition) {
          AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
          //从注解Bean定义类的属性中查找属性为”Scope”的值,即@Scope注解的值
          //annDef.getMetadata().getAnnotationAttributes()方法将Bean
          //中所有的注解和注解的值存放在一个map集合中
          AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
            annDef.getMetadata(), this.scopeAnnotationType);
          //将获取到的@Scope注解的值设置到要返回的对象中
          if (attributes != null) {
            metadata.setScopeName(attributes.getString("value"));
            //获取@Scope注解中的proxyMode属性值,在创建代理对象时会用到
            ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
            //如果@Scope的proxyMode属性为DEFAULT或者NO
            if (proxyMode == ScopedProxyMode.DEFAULT) {
              //设置proxyMode为NO
              proxyMode = this.defaultProxyMode;
            }
            //为返回的元数据设置proxyMode
            metadata.setScopedProxyMode(proxyMode);
          }
        }
        //返回解析的作用域元信息对象
        return metadata;
      }
    }
    

    上述代码中的AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this.scopeAnnotationType);就是获取对象中指定类型的注解的值

    AnnotationConfigUtils处理注释Bean定义类中的通用注解

    AnnotationConfigUtilsprocessCommonDefinitionAnnotations在向容器注册bean之前,首先对注解Bean定义类中的通用Spring注解进行处理,源码如下

    public class AnnotationConfigUtils {
    
      public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
        processCommonDefinitionAnnotations(abd, abd.getMetadata());
      }
    
      //处理Bean定义中通用注解
      static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
        AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
        //如果Bean定义中有@Lazy注解,则将该Bean预实例化属性设置为@lazy注解的值
        if (lazy != null) {
          abd.setLazyInit(lazy.getBoolean("value"));
        }
    
        else if (abd.getMetadata() != metadata) {
          lazy = attributesFor(abd.getMetadata(), Lazy.class);
          if (lazy != null) {
            abd.setLazyInit(lazy.getBoolean("value"));
          }
        }
        //如果Bean定义中有@Primary注解,则为该Bean设置为autowiring自动依赖注入装配的首选对象
        if (metadata.isAnnotated(Primary.class.getName())) {
          abd.setPrimary(true);
        }
        //如果Bean定义中有@ DependsOn注解,则为该Bean设置所依赖的Bean名称,
        //容器将确保在实例化该Bean之前首先实例化所依赖的Bean
        AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
        if (dependsOn != null) {
          abd.setDependsOn(dependsOn.getStringArray("value"));
        }
    
        if (abd instanceof AbstractBeanDefinition) {
          AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
          AnnotationAttributes role = attributesFor(metadata, Role.class);
          if (role != null) {
            absBd.setRole(role.getNumber("value").intValue());
          }
          AnnotationAttributes description = attributesFor(metadata, Description.class);
          if (description != null) {
            absBd.setDescription(description.getString("value"));
          }
        }
      }
    }
    

    AnnotationConfigUtils根据注解Bean定义类中配置的作用域为其应用相应的代理策略

    ​ AnnotationConfigUtils 类的 applyScopedProxyMode()方法根据注解 Bean 定义类中配置的作用域
    @Scope 注解的值,为 Bean 定义应用相应的代理模式,主要是在 Spring 面向切面编程(AOP)中使用。
    源码如下:

    public class AnnotationConfigUtils {
    
      //根据作用域为Bean应用引用的代码模式
      static BeanDefinitionHolder applyScopedProxyMode(
        ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
    
        //获取注解Bean定义类中@Scope注解的proxyMode属性值
        ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
        //如果配置的@Scope注解的proxyMode属性值为NO,则不应用代理模式
        if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
          return definition;
        }
        //获取配置的@Scope注解的proxyMode属性值,如果为TARGET_CLASS
        //则返回true,如果为INTERFACES,则返回false
        boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
        //为注册的Bean创建相应模式的代理对象
        return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
      }
    }
    
    
    public abstract class ScopedProxyUtils {
    
      public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
                                                           BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    
        String originalBeanName = definition.getBeanName();
        BeanDefinition targetDefinition = definition.getBeanDefinition();
        String targetBeanName = getTargetBeanName(originalBeanName);
    
        // Create a scoped proxy definition for the original bean name,
        // "hiding" the target bean in an internal target definition.
        RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
        proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
        proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
        proxyDefinition.setSource(definition.getSource());
        proxyDefinition.setRole(targetDefinition.getRole());
    
        proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
        if (proxyTargetClass) {
          targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
          // ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
        }
        else {
          proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
        }
    
        // Copy autowire settings from original bean definition.
        proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
        proxyDefinition.setPrimary(targetDefinition.isPrimary());
        if (targetDefinition instanceof AbstractBeanDefinition) {
          proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
        }
    
        // The target bean should be ignored in favor of the scoped proxy.
        targetDefinition.setAutowireCandidate(false);
        targetDefinition.setPrimary(false);
    
        // Register the target bean as separate bean in the factory.
        registry.registerBeanDefinition(targetBeanName, targetDefinition);
    
        // Return the scoped proxy definition as primary bean definition
        // (potentially an inner bean).
        return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
      }
    }
    

    BeanDefinitionReaderUtils向容器注册Bean

    BeanDefinitionReaderUtils主要是校验BeanDefinition信息,然后将Bean添加到容器中一个管理BeanDefinition的HashMap中

    //将解析的BeanDefinitionHold注册到容器中
    public static void registerBeanDefinition(
          BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
          throws BeanDefinitionStoreException {
    
       // Register bean definition under primary name.
       //获取解析的BeanDefinition的名称
       String beanName = definitionHolder.getBeanName();
       //向IOC容器注册BeanDefinition
       registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
       // Register aliases for bean name, if any.
       //如果解析的BeanDefinition有别名,向容器为其注册别名
       String[] aliases = definitionHolder.getAliases();
       if (aliases != null) {
          for (String alias : aliases) {
             registry.registerAlias(beanName, alias);
          }
       }
    

    扫描指定包并解析为BeanDefinition

    ​ 当创建注解处理容器时,如果传入的初始参数是注解Bean定义类所在的包是,注解容器将扫描给定的包及其子包,将扫描到的注解Bean定义载入并注册

    ClassPathBeanDefinitionScanner扫描给定的包及其子包

    	//保存一个扫描指定类路径中注解Bean定义的扫描器,并将其设置到容器中
    	private final ClassPathBeanDefinitionScanner scanner;
    
    	//默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()
    	//方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean的载入、解析和注册过程
    	public AnnotationConfigApplicationContext() {
    		this.reader = new AnnotatedBeanDefinitionReader(this);
    		this.scanner = new ClassPathBeanDefinitionScanner(this);
    	}
    	//该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中
    	public AnnotationConfigApplicationContext(String... basePackages) {
    		this();
    		scan(basePackages);
    		refresh();
    	}
    
    //扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用
    //refresh()方法刷新容器
    public void scan(String... basePackages) {
      Assert.notEmpty(basePackages, "At least one base package must be specified");
      this.scanner.scan(basePackages);
    }
    
    public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
    
      //创建一个类路径Bean定义扫描器
      public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this(registry, true);
      }
    
      //为容器创建一个类路径Bean定义扫描器,并指定是否使用默认的扫描过滤规则。
      //即Spring默认扫描配置:@Component、@Repository、@Service、@Controller
      //注解的Bean,同时也支持JavaEE6的@ManagedBean和JSR-330的@Named注解
      public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry,
                                            boolean useDefaultFilters) {
        this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
      }
      public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, 
                                            boolean useDefaultFilters,
                                            Environment environment) {
        this(registry, useDefaultFilters, environment,
             (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
      }
      public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, 
                                            boolean useDefaultFilters,
                                            Environment environment, 
                                            @Nullable ResourceLoader resourceLoader) {
    
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        //为容器设置加载Bean定义的注册器
        this.registry = registry;
    
        if (useDefaultFilters) {
          registerDefaultFilters();
        }
        setEnvironment(environment);
        //为容器设置资源加载器
        setResourceLoader(resourceLoader);
      }
    
      //调用类路径Bean定义扫描器入口方法
      public int scan(String... basePackages) {
        //获取容器中已经注册的Bean个数
        int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    
        //启动扫描器扫描给定包
        doScan(basePackages);
    
        // Register annotation config processors, if necessary.
        //注册注解配置(Annotation config)处理器
        if (this.includeAnnotationConfig) {
          AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
        }
    
        //返回注册的Bean个数
        return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
      }
    
      //类路径Bean定义扫描器扫描给定包及其子包
      protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        //创建一个集合,存放扫描到Bean定义的封装类
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        //遍历扫描所有给定的包
        for (String basePackage : basePackages) {
          //调用父类ClassPathScanningCandidateComponentProvider的方法
          //扫描给定类路径,获取符合条件的Bean定义
          Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
          //遍历扫描到的Bean
          for (BeanDefinition candidate : candidates) {
            //获取Bean定义类中@Scope注解的值,即获取Bean的作用域
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            //为Bean设置注解配置的作用域
            candidate.setScope(scopeMetadata.getScopeName());
            //为Bean生成名称
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            //如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
            //设置Bean的自动依赖注入装配属性等
            if (candidate instanceof AbstractBeanDefinition) {
              postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            //如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解
            if (candidate instanceof AnnotatedBeanDefinition) {
              //处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过
              AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            //根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突
            if (checkCandidate(beanName, candidate)) {
              BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
              //根据注解中配置的作用域,为Bean应用相应的代理模式
              definitionHolder =
                AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
              beanDefinitions.add(definitionHolder);
              //向容器注册扫描到的Bean
              registerBeanDefinition(definitionHolder, this.registry);
            }
          }
        }
        return beanDefinitions;
      }
    }
    

    ClassPathScanningCandidateComponentProvider扫描给定包及其子包的类

    ClassPathScanningCanididateComponentProvider类的findCandidateComponents()方法具体实现扫描类给定类路径包的功能,主要源码如下:

    public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
      //向容器注册过滤规则
      @SuppressWarnings("unchecked")
      protected void registerDefaultFilters() {
        //向要包含的过滤规则中添加@Component注解类,注意Spring中@Repository
        //@Service和@Controller都是Component,因为这些注解都添加了@Component注解
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        //获取当前类的类加载器
        ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
        try {
          //向要包含的过滤规则添加JavaEE6的@ManagedBean注解
          this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
          logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
        }
        catch (ClassNotFoundException ex) {
          // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
        }
        try {
          //向要包含的过滤规则添加@Named注解
          this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
          logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
        }
        catch (ClassNotFoundException ex) {
          // JSR-330 API not available - simply skip.
        }
      }
      //扫描给定类路径的包
      public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
          return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
        }
        else {
          return scanCandidateComponents(basePackage);
        }
      }
      private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsIndex index, String basePackage) {
        //创建存储扫描到的类的集合
        Set<BeanDefinition> candidates = new LinkedHashSet<>();
        try {
          Set<String> types = new HashSet<>();
          for (TypeFilter filter : this.includeFilters) {
            String stereotype = extractStereotype(filter);
            if (stereotype == null) {
              throw new IllegalArgumentException("Failed to extract stereotype from "+ filter);
            }
            types.addAll(index.getCandidateTypes(basePackage, stereotype));
          }
          boolean traceEnabled = logger.isTraceEnabled();
          boolean debugEnabled = logger.isDebugEnabled();
          for (String type : types) {
            //为指定资源获取元数据读取器,元信息读取器通过汇编(ASM)读//取资源元信息
            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);
            //如果扫描到的类符合容器配置的过滤规则
            if (isCandidateComponent(metadataReader)) {
              //通过汇编(ASM)读取资源字节码中的Bean定义元信息
              AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition(
                metadataReader.getAnnotationMetadata());
              if (isCandidateComponent(sbd)) {
                if (debugEnabled) {
                  logger.debug("Using candidate component class from index: " + type);
                }
                candidates.add(sbd);
              }
              else {
                if (debugEnabled) {
                  logger.debug("Ignored because not a concrete top-level class: " + type);
                }
              }
            }
            else {
              if (traceEnabled) {
                logger.trace("Ignored because matching an exclude filter: " + type);
              }
            }
          }
        }
        catch (IOException ex) {
          throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
        }
        return candidates;
      }
    
      private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = new LinkedHashSet<>();
        try {
          String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
          Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
          boolean traceEnabled = logger.isTraceEnabled();
          boolean debugEnabled = logger.isDebugEnabled();
          for (Resource resource : resources) {
            if (traceEnabled) {
              logger.trace("Scanning " + resource);
            }
            if (resource.isReadable()) {
              try {
                MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                if (isCandidateComponent(metadataReader)) {
                  ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                  sbd.setResource(resource);
                  sbd.setSource(resource);
                  if (isCandidateComponent(sbd)) {
                    if (debugEnabled) {
                      logger.debug("Identified candidate component class: " + resource);
                    }
                    candidates.add(sbd);
                  }
                  else {
                    if (debugEnabled) {
                      logger.debug("Ignored because not a concrete top-level class: " + resource);
                    }
                  }
                }
                else {
                  if (traceEnabled) {
                    logger.trace("Ignored because not matching any filter: " + resource);
                  }
                }
              }
              catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                  "Failed to read candidate component class: " + resource, ex);
              }
            }
            else {
              if (traceEnabled) {
                logger.trace("Ignored because not readable: " + resource);
              }
            }
          }
        }
        catch (IOException ex) {
          throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
        }
        return candidates;
      }
    }
    

    注册注解BeanDefinition

    AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext的WEB版,他们对于注解Bean的注册和扫描是基本相同的,但是AnnotationConfigWebApplicationContext对注解Bean定义的载入稍有不同,AnnotationConfigWebApplicationContext注入注解Bean定义源码如下

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
       //为容器设置注解Bean定义读取器
       AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
       //为容器设置类路径Bean定义扫描器
       ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
    
       //获取容器的Bean名称生成器
       BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
       //为注解Bean定义读取器和类路径扫描器设置Bean名称生成器
       if (beanNameGenerator != null) {
          reader.setBeanNameGenerator(beanNameGenerator);
          scanner.setBeanNameGenerator(beanNameGenerator);
          beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
       }
    
       //获取容器的作用域元信息解析器
       ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
       //为注解Bean定义读取器和类路径扫描器设置作用域元信息解析器
       if (scopeMetadataResolver != null) {
          reader.setScopeMetadataResolver(scopeMetadataResolver);
          scanner.setScopeMetadataResolver(scopeMetadataResolver);
       }
    
       if (!this.annotatedClasses.isEmpty()) {
          if (logger.isInfoEnabled()) {
             logger.info("Registering annotated classes: [" +
                   StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
          }
          reader.register(this.annotatedClasses.toArray(new Class<?>[this.annotatedClasses.size()]));
       }
    
       if (!this.basePackages.isEmpty()) {
          if (logger.isInfoEnabled()) {
             logger.info("Scanning base packages: [" +
                   StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
          }
          scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
       }
    
       //获取容器定义的Bean定义资源路径
       String[] configLocations = getConfigLocations();
       //如果定位的Bean定义资源路径不为空
       if (configLocations != null) {
          for (String configLocation : configLocations) {
             try {
                //使用当前容器的类加载器加载定位路径的字节码类文件
                Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
                if (logger.isInfoEnabled()) {
                   logger.info("Successfully resolved class for [" + configLocation + "]");
                }
                reader.register(clazz);
             }
             catch (ClassNotFoundException ex) {
                if (logger.isDebugEnabled()) {
                   logger.debug("Could not load class for config location [" + configLocation +
                         "] - trying package scan. " + ex);
                }
                //如果容器类加载器加载定义路径的Bean定义资源失败
                //则启用容器类路径扫描器扫描给定路径包及其子包中的类
                int count = scanner.scan(configLocation);
                if (logger.isInfoEnabled()) {
                   if (count == 0) {
                      logger.info("No annotated classes found for specified class/package [" + configLocation + "]");
                   }
                   else {
                      logger.info("Found " + count + " annotated classes in package [" + configLocation + "]");
                   }
                }
             }
          }
       }
    }
    

    IOC容器初始化小结

    ​ 现在通过上面的代码,总结一下IOC容器初始化的基本步骤:

    ​ 1.初始化的入口在容器实现中的refresh()调用来完成

    ​ 2.对Bean定义载入IOC容器使用的方式是loadBeanDefinition()

    ​ 其中的大致过程如下:

    ​ 通过ResouceLoader来完成资源文件位置的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader的实现,可以从类路径,文件系统,URL等方式来定位资源文件,如果是XmlBeanFactory作为IOC容器,那么需要为它指定Bean定义的资源,也就是说Bean定义文件是通过抽象成Resouce来呗IOC容器处理的,容器通过BeanDefinitionReader来完成定义信息的解析和Bean信息的注册,往往使用的是XmlBeanDefintionReader来解析Bean的XML定义文件,实际处理过程是委托给BeanDefinitionParserDelegate来完成的,从而得到Bean的定义信息,这些信息在Spring中使用BeanDefinition对象来表示,这个名字可以让我们想到loadBeanDefinition(),registerBeanDefinition()这些相关方法,他们都是为处理BeanDefinition服务的,容器解析得到BeanDefiniton以后,需要把它在IOC容器中注册,这由IOC实现BeanDefinitionRegistry接口来实现。注册过程就是在IOC容器内部维护的一个HashMap来保存得到的BeanDefinition的过程,这个HashMap是IOC容器持有的Bean信息的场所,以后对Bean的操作都是围绕这个HashMap来实现的。

    ​ 然后我们就可以使用BeanFactoryApplicationContext来享受到SpringIOC的服务了,在使用IOC容器的时候,我们注意到除了少量粘合代码,绝大多数以正确IOC风格编写的应用程序代码完全不用关心如何到达工厂,因为容器把这些对象和容器管理的其他对象关联在一起,基本的策略是把工厂放到已知的地方,最好是放在对预期使用的上下文有意义的地方,以及代码将实际需要访问工厂的地方。Spring本身提供了对声明式载入web应用程序用法的应用程序上下文,将其存储在ServletContext的框架实现。

    ioc容器时序图

    展开全文
  • spring ioc源码剖析

    2021-04-20 12:45:22
    spring ioc源码剖析 ioc的定义IOC核心类与类关系BeanDifinition:如何定义一个beanBeanDefinitionRegistry:注册bean定义的接口AnnotationConfigApplicationContextGenericApplicationContext与...
  • Spring IOC 源码分析

    2019-12-29 16:25:08
    Spring IOC源码分析 源码解读困难点: 1、自定义标签解析 2、循环依赖 3、后置处理器 扩展点: 1、声明式Aop通过FactoryBean实现 2、AspectJ式的AOP通过后置处理器实现 3、类注解、类内属性注解通过后置...
  • spring IOC源码分析(1)

    万次阅读 2011-09-02 14:22:17
    1.何谓Spring IOC  何谓Spring IOC?书上谓之“依赖注入”,那何谓“依赖注入”?  作为一个Java程序猿,应该遇到过这样的问题,当你在代码中需要使用某个类提供的功能时,你首先需要new一个对象,给它传递必要...
  • public class A { } public class B { }
  • SpringIoc 源码分析

    2018-11-14 11:21:44
    Spring IOC 容器源码分析 (转载自 https://javadoop.com/post/spring-ioc?hmsr=toutiao.io&amp;amp;utm_medium=toutiao.io&amp;amp;utm_source=toutiao.io) Spring 最重要的概念是 IOC 和 AOP,本篇文章其实...
  • springIOC源码分析

    2018-12-20 11:10:58
    教你看spring框架源码。。。 好像也不难!!! ioc原理 : 反射 + dom4j解析xml 其他方式的注入大同小异,所谓的ioc容器就是一个一个的map,为什么控制反转了呢,因为你把本应该jvm管理的对象放进...
  • spring IOC 源码分析

    2019-07-09 17:44:04
    原文链接

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,226
精华内容 14,490
关键字:

springioc源码分析

spring 订阅