Spring核心容器实现之容器初始化

16 篇文章 0 订阅
14 篇文章 0 订阅

调用时序图

容器实现的实现代码庞杂,完全抽象出来其实仅仅三个步骤:资源定位、资源加载、资源注册;

       DefaultListableBeanFactory 类是核心容器,且主要实现注册的核心逻辑,并通过上下文传递的方式在最后实现注册

       AbstractRefreshableApplicationContext   及其子类则是为了实现良好的扩展性,对资源定位进行的封装,针对注解、xml、其他配置等提供不同的资源定位实现

       在加载过程中主要采用的策略模式:NamespaceHandler  和 BeanDefinitionParser + BeanDefaultReader 实现资源加载

 

体系设计1,BeanFactory:Bean工厂  为IOC容器管理对象间依赖关系提供基础服务。

        顶层接口:BeanFactory,定义IOC容器基本功能规范,在spring中万物皆对象,万物皆工厂;因此BeanFactory与FactoryBean一样为一切类的初始,(其后定义Bean集合和Bean之间关系的接口有:  ListableBeanFactory-可列表Bean、HierarchicalBeanFactory -继承关系Bean、AutowireCapableBeanFactory - 自动装配规则Bean;)

        第二层行为类接口:ResourceLoader - 资源加载、AliasRegistry - BeanDefinition的注册、 NamespaceHandler - 命名空间处理器、 BeanDefinitionParser - BeanDefinition解析器 、

        其他外部扩展接口:BeanNameAware - 提供的外部扩展接口、InitializingBean- 提供的外部扩展接口

        第三层具体实现:  默认实现:DefaultListableBeanFactory,实现了所有接口;

                 具体的IOC容器实现:XmlBeanFactory,ClasspathXmlApplicationContext 等;

                多层次接口实现原因: 区分操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。

类图中有趣的设计模式点

//ApplicationContext parent   实现类似双亲委派模式
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {

    private ApplicationContext parent;
    private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors;
    private Thread shutdownHook;
    private ResourcePatternResolver resourcePatternResolver;
    private MessageSource messageSource;
    private ApplicationEventMulticaster applicationEventMulticaster;
    private final Set<ApplicationListener<?>> applicationListeners;
    private Set<ApplicationEvent> earlyApplicationEvents;

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

    public AbstractApplicationContext(ApplicationContext parent) {
        this();
        this.setParent(parent);
    }
}

 

//AbstractBeanFactory:  parentBeanFactory 实现子类与父类关系的维护
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    private BeanFactory parentBeanFactory;

    public AbstractBeanFactory() {
    }

    public AbstractBeanFactory(BeanFactory parentBeanFactory) {
        this.parentBeanFactory = parentBeanFactory;
    }

}
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
    private Boolean allowBeanDefinitionOverriding;
    private Boolean allowCircularReferences;

    //静态代理模式:  DefaultListableBeanFactory 作为实现核心,
    //            里面存储所有的容器核心参数,是实现BeanDefinition注册的真正实现
    private DefaultListableBeanFactory beanFactory;
    // 这里为何新建一个 beanFactoryMonitor 作为加锁对象呢???
    private final Object beanFactoryMonitor = new Object();


    protected final void refreshBeanFactory() throws BeansException {
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
            //加载BeanDefinition的实现方法
            this.loadBeanDefinitions(beanFactory);
            //加锁为何要如此实现呢?
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }
}
DefaultListableBeanFactory核心容器主要参数

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    private static Class javaxInjectProviderClass = null;
    private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories;
    private String serializationId;
    private boolean allowBeanDefinitionOverriding = true;
    private boolean allowEagerClassLoading = true;
    private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
    private final Map<Class, Object> resolvableDependencies = new HashMap();
    //spring核心IOC容器
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap();
    private final List<String> beanDefinitionNames = new ArrayList();
    private boolean configurationFrozen = false;
    private String[] frozenBeanDefinitionNames;

    static {
        ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();

        try {
            javaxInjectProviderClass = cl.loadClass("javax.inject.Provider");
        } catch (ClassNotFoundException var1) {
        }

        serializableFactories = new ConcurrentHashMap();
    }
}
ClassPathXmlApplicationContext启动类
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
    //实现自己特有的方式的资源加载
    private Resource[] configResources;

    
    //父类通过子类重写该方法实现获取子类资源信息
    @Override    
    protected Resource[] getConfigResources() {
        return null;
    }
}

体系设计2,BeanDefinition: 定义描述bean对象及其相互关系;及实现BeanDefinition初始化接口

       BeanDefinition来实现对Bean对象的描述,解析过程非常复杂,功能主要被XmlBeanDefinitionReader实现;

          主要实现     XmlBeanDefinitionReader   是类 AbstractXmlApplicationContext中new进行创建,并调用加载注册;

          整个调用过程的:  XmlBeanDefinitionReader - NamespaceHandlerResolver - NamespaceHandler - BeanDefintionParser - BeanDefinitionRegistry 实现解析和注册()

ApplicationContext


读取文档上下文对象:
ReaderContext{
	Resource    解析资源
	ProblemReporter   
	ReaderEventListener   时间监听
	SourceExtractor    
}
XmlReaderContext extends ReaderContext {
	XmlBeanDefinitionReader{
		BeanDefinitionRegistry      bena注册器
		loadBeanDefinitions(Resource... resources)  -- 将resource地址转换为XML的Documnet
	}
	NamespaceHandlerResolver    解析handler
	
	registerWithGeneratedName(BeanDefinition beanDefinition)  -- 
}

XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.namespaceHandlerResolver)



解析上下文对象
new ParserContext(this.readerContext, this, containingBd){
	XmlReaderContext
	BeanDefinitionParserDelegate
	BeanDefinition
}


策略对象1: NamespaceHandler = XmlReaderContext.getNamespaceHandlerResolver().resolve(namespaceUri)
NamespaceHandler.parse(ele, new ParserContext(this.readerContext, this, containingBd));


策略对象2: BeanDefinitionParser = (BeanDefinitionParser)this.parsers.get(ParserContext.getDelegate().getLocalName(element))


最终完成注册:
	BeanDefinitionRegistry实现注册写入数据

 

3、IOC容器初始化过程:初始化过程包含 Resource定位、载入、注册三个过程;

        ApplicationContext 是我们最熟悉的上下文容器,其实现包括 XmlWebApplicationContext、ClasspathXmlApplicationContext、 FileSystemXmlApplicationContext;   其采用类加载器的设计方式,允许上下文嵌套,当Bean查找在当前上下文找不到,则取父上下文查找,逐级向上。

        【实现原因】:实现共享的Bean定义环境;

         ①源码实现: XmlBeanFactory

// 根据Xml 配置文件创建Resource 资源对象,该对象中包含了BeanDefinition 的信息
ClassPathResource resource = new ClassPathResource("application-context.xml");
// 创建DefaultListableBeanFactory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//创建XmlBeanDefinitionReader 读取器,用于载入BeanDefinition。
// 之所以需要BeanFactory 作为参数,是因为会将读取的信息回调配置给factory
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
// XmlBeanDefinitionReader 执行载入BeanDefinition 的方法,最后会完成Bean 的载入和注册。
// 完成后Bean 就成功的放置到IOC 容器当中,以后我们就可以从中取得Bean 来使用
reader.loadBeanDefinitions(resource);

         ②源码实现:FileSystemXmlApplicationContext

                构造函数调用:

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
    super(parent);     //调用1:默认实现 AbstractApplicationContext,为容器设置Bean资源加载器
    setConfigLocations(configLocations);   //调用2:设置Bean定义资源文件的定位路径。
    if (refresh) {
        refresh();     //调用3:刷新容器, 载入Bean定义;
    }
}



//调用1、父类初始化实现
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);
    }
    ...
}


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



//调用2:处理单个资源文件路径为一个字符串的情况
public void setConfigLocation(String location) {
    //String CONFIG_LOCATION_DELIMITERS = ",; /t/n";
    //即多个资源文件路径之间用” ,; \t\n”分隔,解析成数组形式
    setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
}

//解析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;
    }
}




//调用3   容器存在则销毁和关闭,并新建IOC容器;AbstractApplicationContext 类实现
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
        prepareRefresh();
        
        //调用3-1、告诉子类启动refreshBeanFactory()方法,Bean 定义资源文件的载入从
        //子类的refreshBeanFactory()方法启动
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        //为BeanFactory 配置容器特性,例如类加载器、事件处理器等
        prepareBeanFactory(beanFactory);
        try {
            //为容器的某些子类指定特殊的BeanPost 事件处理器
            postProcessBeanFactory(beanFactory);
        
            //调用所有注册的BeanFactoryPostProcessor 的Bean
            invokeBeanFactoryPostProcessors(beanFactory);

            //为BeanFactory 注册BeanPost 事件处理器.
            //BeanPostProcessor 是Bean 后置处理器,用于监听容器触发的事件
            registerBeanPostProcessors(beanFactory);

            //初始化信息源,和国际化相关.
            initMessageSource();

            //初始化容器事件传播器.
            initApplicationEventMulticaster();

            //调用子类的某些特殊Bean 初始化方法
            onRefresh();

            //为事件传播器注册事件监听器.
            registerListeners();

            //初始化所有剩余的单例Bean
            finishBeanFactoryInitialization(beanFactory);

            //初始化容器的生命周期事件处理器,并发布容器的生命周期事件
            finishRefresh();
        }
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);
            }
            //销毁已创建的Bean
            destroyBeans();
            //取消refresh 操作,重置容器的同步标识.
            cancelRefresh(ex);
            throw ex;
        }
        finally {
            resetCommonCaches();
        }
    }
}




//调用3-1、告诉子类启动refreshBeanFactory()方法
// AbstractApplicationContext # obtainFreshBeanFactory() 中调用子类实现 refreshBeanFactory
// 真正调用  AbstractRefreshableApplicationContext 的实现;
protected final void refreshBeanFactory() throws BeansException {
    //如果已经有容器,销毁容器中的bean,关闭容器
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        //创建IOC 容器
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());

        //对IOC 容器进行定制化,如设置启动参数,开启注解的自动装配等
        customizeBeanFactory(beanFactory);

        //调用3-1-1,载入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);
    }
}




//调用3-1-1、载入Bean 定义的方法,主要这里又使用了一个委派模式,
//在当前类中只定义了抽象的loadBeanDefinitions方法,具体由子类AbstractXmlApplicationContext容器实现;
public abstract class AbstractXmlApplicationContext extends         AbstractRefreshableConfigApplicationContext {
    ...
    //实现父类抽象的载入Bean 定义方法
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {

        //创建XmlBeanDefinitionReader,即创建Bean 读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean 定义资源
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        //为Bean 读取器设置Spring 资源加载器,AbstractXmlApplicationContext 的
        //祖先父类AbstractApplicationContext 继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);

        //为Bean 读取器设置SAX xml 解析器
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        //当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) {
            //调用3-1-1-1、Xml Bean 读取器调用其父类AbstractBeanDefinitionReader 读取定位
            //的Bean 定义资源
            reader.loadBeanDefinitions(configLocations);
        }
    }

    //这里又使用了一个委托模式,调用子类的获取Bean 定义资源定位的方法
    //该方法在ClassPathXmlApplicationContext 中进行实现,对于我们
    //举例分析源码的FileSystemXmlApplicationContext 没有使用该方法
    @Nullable
    protected Resource[] getConfigResources() {
        return null;
    }
}




//调用3-1-1-1、读取器调用其父类AbstractBeanDefinitionReader 读取定位的Bean定义资源

//重载方法,调用下面的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 {

            //调用3-1-1-1-1、将指定位置的Bean 定义资源文件解析为Spring IOC 容器封装的资源
            //加载多个指定位置的Bean 定义资源文件
            Resource[] resources = ((ResourcePatternResolver)     resourceLoader).getResources(location);

            //调用3-1-1-1-2,资源加载要获取的资源:委派调用其子类XmlBeanDefinitionReader的loadBeanDefinitions方法,实现加载功能,实际实现为DefaultResourceLoader # getSource()
            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 定义资源文件解析为Spring 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;
    }
}

//重载方法,调用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;
}




 //调用3-1-1-1-1、实际实现为DefaultResourceLoader # getSource()获取Resource 的具体实现方法
@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 文件的资源对象
            URL url = new URL(location);
            return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
        }catch (MalformedURLException ex) {

            //如果既不是classpath 标识,又不是URL 标识的Resource 定位,则调用
            //容器本身的getResourceByPath 方法获取Resource
            return getResourceByPath(location);
        }
    }
    
}



//调用3-1-1-1-2,委派调用其子类XmlBeanDefinitionReader的loadBeanDefinitions方法实现
//功能2:加载BeanDefinition  

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    //将读入的XML 资源进行特殊编码处理
    return loadBeanDefinitions(new EncodedResource(resource));
}

//这里是载入XML 形式Bean 定义资源文件方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    ...
    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();
        }
    }
    ...
}

//从特定XML 文件中实际载入Bean 定义资源的方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
    try {
        //调用1,3-1-1-1-2-1、将XML 文件转换为DOM 对象,解析过程由documentLoader 实现,这里调用的JAVAEE标准的JAXP标准,解析意义不大,跳过;
        Document doc = doLoadDocument(inputSource, resource);

        //调用2,3-1-1-1-2-2、这里是启动对Bean 定义解析的详细过程,该解析过程会用到Spring 的Bean 配置规则;
        return registerBeanDefinitions(doc, resource);
    }
    ...
}


//按照Spring 的Bean 语义要求将Bean 定义资源DOCument转换为容器内部数据结构BeanDefinition;  实现类为DefaultBeanDefinitionDocumentReader
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //得到BeanDefinitionDocumentReader 来对xml 格式的BeanDefinition 解析
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    
    //获得容器中注册的Bean 数量
    int countBefore = getRegistry().getBeanDefinitionCount();

    //调用3,3-1-1-1-2-3解析过程入口,
    //这里使用了委派模式,BeanDefinitionDocumentReader 只是个接口,
    //具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader 完成
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

    //统计解析的Bean 数量
    return getRegistry().getBeanDefinitionCount() - countBefore;
}




//※调用3※,3-1-1-1-2-3解析过程入口,DefaultBeanDefinitionDocumentReader # registerBeanDefinitions()
//根据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);
}
...

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);

    //※调用3,3-1-1-1-2-3-1从Document 的根元素开始进行Bean 定义的Document 对象
    parseBeanDefinitions(root, this.delegate);

    //在解析Bean 定义之后,进行自定义的解析,增加解析过程的可扩展性
    postProcessXml(root);
    this.delegate = parent;
}


//创建BeanDefinitionParserDelegate,用于完成真正的解析过程
protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, @Nullable         BeanDefinitionParserDelegate parentDelegate) {
    BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);

    //BeanDefinitionParserDelegate 初始化Document 根元素
    delegate.initDefaults(root, parentDelegate);
    return delegate;
}


//※使用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 元素节点:<Import> <Alias> <Bean> 
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    //如果元素节点是<Import>导入元素,进行导入解析 [可以导入xml配置文件]
    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);
    }
    //嵌套bean解析
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}


//1、解析标签<Import>导入元素,从给定的导入路径加载其他资源到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;
    }

    //使用系统变量值解析location 属性值
    location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
    Set<Resource> actualResources = new LinkedHashSet<>(4);
    //标识给定的导入元素的location 是否是绝对路径
    boolean absoluteLocation = false;
    try {
        absoluteLocation = ResourcePatternUtils.isUrl(location) ||             ResourceUtils.toURI(location).isAbsolute();
    }catch (URISyntaxException ex) {
        //给定的导入元素的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 {
        //给定的导入元素的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));
}


//2、解析<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));
    }
}


//※3、解析Bean 定义资源Document 对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {

    //BeanDefinitionHolder 是对BeanDefinition 的封装,即Bean 定义的封装类
    //对Document 对象中<Bean>元素的解析由BeanDefinitionParserDelegate 实现
    // 处理<bean>标签的id  ,name, alias属性(ele,BeanDefinition);
    //       及其他属性解析(ele,beanName,BeanDefinition);类名、父类、单例、描述信息、lookup-Method、replaced-Method、property{ 获取元素名字,获取元素,获取不到则创建,解析其属性- 基本类型,ref、list,set、array、map,properties等类型 }、qualifier;
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            //调用3,3-1-1-1-2-3-1、向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);
        }

        //调用3,3-1-1-1-2-3-2、在完成向Spring IOC 容器注册解析得到的Bean 定义之后,发送注册事件
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}





//※调用3,3-1-1-1-2-3-1、将解析的BeanDefinitionHold 注册到容器中; BeanDefinitionReaderUtils # registerBeanDefinition()
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    //获取解析的BeanDefinition 的名称
    String beanName = definitionHolder.getBeanName();

    //调用3,3-1-1-1-2-3-1-1向IOC 容器注册BeanDefinition
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    //如果解析的BeanDefinition 有别名,向容器为其注册别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}



//调用3,3-1-1-1-2-3-1-1向IOC 容器注册BeanDefinition  实现类 DefaultListableBeanFactory

//存储注册信息的BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

//向IOC 容器注册解析的BeanDefiniton,这里并没有注册实例化bean;
@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()) {
            //注册的过程中需要线程同步,以保证数据的一致性(完成了IOC容器初始化)
            //这里beanDefinitionMap 为ConcurrentHashMap为何还需要锁? 因为其中的put、contains、remove不是原子性操作;
            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 {
            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);
    }
}

 

使用SpringIOC服务: spring提供声明式载入web应用程序来存储ServletContext;

 

         最后,我们的Spring   IOC容器就初始化好了,初始化好了之后,这里我们的Bean还没有真正的实例化,在容器中保管的仅仅是BeanDefinition,后面的实例化过程和依赖注入又是怎么实现的呢?

 

阿里大佬带看源码链接:请点击这里

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值