栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

【源码】Spring源码解析(一)IOC容器

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【源码】Spring源码解析(一)IOC容器

文章目录

前言BeanFactory继承结构ApplicationContext 的继承结构容器启动流程分析

创建BeanFactory,加载注册Bean准备BeanFactory初始化所有单例Bean Bean的生命周期

实例化对象设置对象属性检查Aware接口并设置相关依赖BeanPostProcessor前置处理InitializingBean接口检查是否配置自定义的init-methodBeanPostProcessor后置处理DisposableBean接口和destroy方法 总结参考资料

Spring源码合集:
Spring源码解析(一)IOC容器

前言

本章我们要分析的是使用 ClassPathXmlApplicationContext 读取 xml 配置文件启动 Spring 的源码流程。在梳理流程之前,我们需要对 Spring 容器的继承结构有一个大致的认识(有一些读过 Spring 源码的小伙伴应该有这样一种感觉,为啥 Spring 源码跳来跳去的,往往一个方法要重载,重写多次,最后跟了很久才到真正干事的地方。我个人觉得这就是 Spring 源码很精髓的一个点,是对“面向对象”和“设计模式”一种精妙的运用。想要感受这种设计的妙处,Spring 容器的继承结构是一个很好的出发点)。

BeanFactory继承结构

这里先给出 BeanFactory 的继承结构图。

下面列出我认为比较重要的接口,建议读者可以打开源码看一下这些接口。

BeanFactory 接口
Bean 工厂的根接口,提供了获取单个 Bean 实例的基本方法(根据类型,名称…)

使用到的设计模式:

简单工厂模式单例模式原型模式(prototype 原型),生成多例对象时是通过序列化来进行深拷贝。

BeanFactory 中的方法:

interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;

     T getBean(String name, Class requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

     T getBean(Class requiredType) throws BeansException;

     T getBean(Class requiredType, Object... args) throws BeansException;

     ObjectProvider getBeanProvider(Class requiredType);

     ObjectProvider getBeanProvider(ResolvableType requiredType);

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException;

    @Nullable
    Class getType(String name) throws NoSuchBeanDefinitionException;

    @Nullable
    Class getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);
}

ListableBeanFactory 接口

继承 BeanFactory 接口,提供了根据类型、名称,注解等获取 Bean 集合(多个 bean,前面 BeanFactory 只支持获取单个 bean)的方法。

比如:

interface ListableBeanFactory {

    boolean containsBeanDefinition(String beanName);

    int getBeanDefinitionCount();

    String[] getBeanDefinitionNames();

    String[] getBeanNamesForType(ResolvableType type);

    String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);

    String[] getBeanNamesForType(@Nullable Class type);

    String[] getBeanNamesForType(@Nullable Class type, boolean includeNonSingletons, boolean allowEagerInit);

     Map getBeansOfType(@Nullable Class type) throws BeansException;

     Map getBeansOfType(@Nullable Class type, boolean includeNonSingletons, boolean allowEagerInit)
        throws BeansException;

    String[] getBeanNamesForAnnotation(Class annotationType);

    Map getBeansWithAnnotation(Class annotationType) throws BeansException;

    @Nullable
     A findAnnotationOnBean(String beanName, Class annotationType)
        throws NoSuchBeanDefinitionException;
}

HierarchicalBeanFactory 接口

继承BeanFactory接口,允许以可配置的方式设置父级的工厂

interface HierarchicalBeanFactory {
    
    @Nullable
    BeanFactory getParentBeanFactory();

    
    boolean containsLocalBean(String name);
} 

AutowireCapableBeanFactory 接口

继承 BeanFactory 接口,autowire 我们非常熟悉,这个接口主要用于自动装配 Bean。

里面有一些很重要(熟悉,如果你看过 bean 创建流程源码的话)的方法:

interface AutowireCapableBeanFactory {
    int AUTOWIRE_NO = 0;

    int AUTOWIRE_BY_NAME = 1;

    int AUTOWIRE_BY_TYPE = 2;

    int AUTOWIRE_ConSTRUCTOR = 3;

    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;

     T createBean(Class beanClass) throws BeansException;

    Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

    void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;

    Object initializeBean(Object existingBean, String beanName) throws BeansException;

    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
                throws BeansException;

    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException;

    void destroyBean(Object existingBean);

    @Nullable
        Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;

    @Nullable
        Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
                @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
}

ConfigurableBeanFactory 接口

继承 HierarchicalBeanFactory,SingletonBeanRegistry,它的方法主要是对 Bean 工厂进行配置,主要是框架内部使用。

SingletonBeanRegistry 提供对单例对象的一些操作。

ConfigurableListableBeanFactory 接口

它的特殊之处在于继承了 ConfigurableBeanFactory,ListableBeanFactory ,AutowireCapableBeanFactory三个接口(也就是说它会拥有这个三个接口所拥有的功能,后面会看到DefaultListableBeanFactory 就是继承这个接口的)。

ApplicationContext 的继承结构

这是 ApplicationContext 的继承结构图。

ApplicationContext 官方介绍:

为应用程序提供配置的中央接口。
在应用程序运行时,这是只读的,但如果实现类支持,可以重新加载(刷新refresh)。

ApplicationContext提供:

访问应用程序组件的Bean工厂方法。继承自{@link org.springframework.beans.factory.ListableBeanFactory}。以通用方式加载文件资源的能力。继承自{@link org.springframework.core.io.ResourceLoader}接口。向注册的侦听器发布事件的能力。继承自{@link ApplicationEventPublisher}接口。能够解析消息,支持国际化。继承自{@link MessageSource}接口。从父上下文继承。后代上下文中的定义将始终优先考虑。例如,这意味着单亲家长整个web应用程序都可以使用上下文,而每个servlet都有它自己的子上下文独立于任何其他servlet的子上下文。

除了标准的{@link org.springframework.beans.factory.BeanFactory}生命周期功能、ApplicationContext实现、检测和调用{@link ApplicationContextAware}bean以及{@link resourceLoaderware},{@link ApplicationEventPublisherAware}和{@link MessageSourceAware}bean。

这些内容都会在后面的源码中得到体现。

ConfigurableApplicationContext
提供一些SPI接口(会被大多数实现类实现)和一些来配置ApplicationContext的方法。(refresh方法就是在这个类中定义的,后面分析源码会提到)

AbstractApplicationContext
采用模板方法模式,里面定义了很多属性和抽象方法,抽象方法需要子类实现。

FileSystemXmlApplicationContext
构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。

AnnotationConfigApplicationContext
基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置。

容器启动流程分析

首先我们先写一个简单的例子,启动Spring容器。
1.导入Spring依赖
2.创建类

// class: MainTest
public class MainTest {
	public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
		HelloService helloService = (HelloService) applicationContext.getBean("helloService");
		helloService.hello();
	}
}

// interface: HelloService
public interface HelloService {
	void hello();
}

// class: HelloServiceImpl
public class HelloServiceImpl implements HelloService {
	@Override
	public void hello() {
		System.out.println("你好呀~");
	}
}

3.编写配置文件 spring.xml




	

4.编译启动主类

我们是使用配置文件来构建 Spring 容器的,构建容器主要的逻辑应该下面这段代码中:

public class MainTest {
	public static void main(String[] args) {
        // 构建 Spring 容器
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
		...
	}
}

跟进去看

// ClassPathXmlApplicationContext 84
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    // 参数一: 配置文件位置
    // 参数二: 是否刷新(执行 refresh 方法)
    // 调用重载的构造方法
    this(new String[] {configLocation}, true, null);
}

// 继续看
// ClassPathXmlApplicationContext 139
public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
    // 设置父容器, 此处为 null(注: 个人感觉父容器和类加载器的双亲委派模型有一些相似之处)
    // 最终是设置到(父类 AbstractApplicationContext 的 parent 属性中,之前提到过 AbstractApplicationContext 使用了模板方法模式,里面定义了很多属性和抽象方法,抽象方法需要子类实现)
    super(parent);
    // 设置配置文件地址(父类 AbstractRefreshableConfigApplicationContext 的方法)
    setConfigLocations(configLocations);
    // 刷新容器, 重点!!
    if (refresh) {
        // (父类 AbstractApplicationContext 中的方法)
        // (接口 ConfigurableApplicationContext 的方法)
        refresh();
    }
}

我们继续跟进到refresh方法中,refresh方法负责刷新容器,非常重要!

可以看到refresh方法中干了很多事情,下面会列举比较重要的方法具体展开:

// AbstractApplicationContext 533
// 继续跟进到 refresh 方法中
public void refresh() throws BeansException, IllegalStateException {
    // BeansException: 容器初始化失败,抛出此异常
    // IllegalStateException: 容器初始化完成后, 若再次进行 refresh, 抛出此异常

    // synchronized 保证线程安全性
    synchronized (this.startupShutdownMonitor) {
        // 设置启动时间,标志"启动"状态,验证标记为"需要"的配置文件都是可解析的,
        prepareRefresh();

        // ConfigurableListableBeanFactory 接口: 继承了ConfigurableBeanFactory,ListableBeanFactory ,AutowireCapableBeanFactory 三个接口
        // 重要!! 创建BeanFactory(类型: DefaultListableFactory),读取 xml 文件中定义的 bean 信息为 beanDefinition,注册到 BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        prepareBeanFactory(beanFactory);

        try {
            // 到目前,所有 bean 的加载、注册都完成了,但是都还没有初始化
            // 扩展点: 子类可以在这里添加 BeanFactoryPostProcessor,做一些事情
            postProcessBeanFactory(beanFactory);

            // 调用各个 BeanFactoryPostProcessor 实现类的 postProcessBeanFactory(factory) 方法
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册所有 BeanPostProcessor
            // BeanPostProcessor 有两个方法,postProcessBeforeInitialization 和 postProcessAfterInitialization,这两个方法在 bean 初始化之前和之后执行
            // BeanPostProcessor 可以进行优先级排序
            registerBeanPostProcessors(beanFactory);

            // 初始化 ApplicationContext 的 MessageSource,国际化
            initMessageSource();

            // 初始化 ApplicationContext 的事件广播器
            initApplicationEventMulticaster();

            // 扩展点: 模板方法,可以在初始化特殊 bean 的时候调用
            onRefresh();

            // 注册事件监听器,监听器需要实现 ApplicationListener 接口
            registerListeners();

            // 初始化所有单例 Bean(标注了 lazy-init 的 bean 除外)
            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 {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

首先是一个 synchronized 同步块,保证线程的安全,这个不用多说。

然后是prepareRefresh方法,它是在容器刷新前做一些准备工作(它也是 AbstractApplicationContext 中的模板方法):

// AbstractApplicationContext 625
protected void prepareRefresh() {
    // 启动时间
    this.startupDate = System.currentTimeMillis();
    // 标记启动状态
    this.closed.set(false);
    this.active.set(true);

    if (logger.isDebugEnabled()) {
        if (logger.isTraceEnabled()) {
            logger.trace("Refreshing " + this);
        }
        else {
            logger.debug("Refreshing " + getDisplayName());
        }
    }

    // 默认什么都不做
    initPropertySources();

    // 验证所需要的配置文件是否都可以解析
    getEnvironment().validateRequiredProperties();

    // Store pre-refresh ApplicationListeners...
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new linkedHashSet<>(this.applicationListeners);
    }
    else {
        // Reset local application listeners to pre-refresh state.
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    this.earlyApplicationEvents = new linkedHashSet<>();
}
创建BeanFactory,加载注册Bean

接下来是一个非常重要的方法 obtainFreshBeanFactory,这个方法中创建了 BeanFactory,并且读取 xml 配置文件的信息,将 xml 中定义的 bean 信息加载成 BeanDefinition 并注册到 BeanFactory 中。

// AbstractApplicationContext 681
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 调用 AbstractRefreshableApplicationContext 中的 refreshBeanFactory 实现
    // refreshBeanFactory 是 AbstractApplicationContext 中的抽象方法,由 AbstractRefreshableApplicationContext 实现
    refreshBeanFactory();
    return getBeanFactory();
}

// AbstractRefreshableApplicationContext 121
protected final void refreshBeanFactory() throws BeansException {
    // 销毁已经存在 BeanFactory
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 创建 DefaultListableBeanFactory, 这个类是最下层的类(可以回去看看 BeanFactory 的继承结构图),可以向上转型成它的各个父类/接口
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        // 扩展配置: 是否允许 BeanDefinition 覆盖,是否允许循环依赖
        // 这两个配置默认都是 null
        customizeBeanFactory(beanFactory);
        // 调用 AbstractXmlApplicationContext 的 loadBeanDefinitions 方法实现 
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

loadBeanDefinitions 是 AbstractRefreshableApplicationContext 的一个抽象方法,子类 AbstractXmlApplicationContext 实现这个方法,继续跟进到 loadBeanDefinitions 方法中。

// AbstractXmlApplicationContext 81
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 先创建一个 XmlBeanDefinitionReader,根据名字很好判断这个类是干什么的
    // XmlBeanDefinitionReader: 读取 xml 文件,将里面的 Bean 定义信息读取为 BeanDefinition,加载到 BeanFactory 中
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // 配置 XmlBeanDefinitionReader
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    initBeanDefinitionReader(beanDefinitionReader);
    // 执行从 xml 文件读取 Bean 定义信息为 BeanDefinition 并注册到 BeanFactory 的操作
    // 调用重载方法,传入 XmlBeanDefinitionReader
    loadBeanDefinitions(beanDefinitionReader);
}

// 继续跟进 loadBeanDefinitions 方法
// AbstractXmlApplicationContext 125
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    // 我们配置了 xml 文件的地址,所以是执行下面的操作
    String[] configLocations = getConfigLocations();
    // 得到 configLocations = ["spring.xml"]
    if (configLocations != null) {
        // reader 执行将配置文件读取为 BeanDefinition 并注册到 BeanFactory 的操作
        reader.loadBeanDefinitions(configLocations);
    }
}

// 跟进到 reader 的 loadBeanDefinitions 中
// AbstractBeanDefinitionReader 258
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int count = 0;
    for (String location : locations) {
        // reader 执行将配置文件读取为 BeanDefinition 并注册到 BeanFactory 的操作
        // 调用重载,读取单个 location 的配置信息
        count += loadBeanDefinitions(location);
    }
    return count;
}

// AbstractBeanDefinitionReader 195
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    // reader 执行将配置文件读取为 BeanDefinition 并注册到 BeanFactory 的操作
    // 继续调用重载
    return loadBeanDefinitions(location, null);
}

// AbstractBeanDefinitionReader 215
public int loadBeanDefinitions(String location, @Nullable Set actualResources) throws BeanDefinitionStoreException {
    // resourceLoader 类型: ClassXmlApplicationContext
    // 为啥这里是 ClassXmlApplicationContext?
    // 仔细看 ApplicationContext 接口,它实现了 ResourcePatternResolver 这个接口,ResourcePatternResolver 又是继承的 ResourceLoader 接口,所以可以转型。
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
            "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
        try {
            // resources: [spring.xml]
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            // reader 执行将配置文件读取为 BeanDefinition 并注册到 BeanFactory 的操作
            // 继续调用重载,这里传入的是 Resource 数组
            int count = loadBeanDefinitions(resources);
            if (actualResources != null) {
                Collections.addAll(actualResources, resources);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
            }
            return count;
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                "Could not resolve bean definition resource pattern [" + location + "]", ex);
        }
    }
    else {
        Resource resource = resourceLoader.getResource(location);
        int count = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
        }
        return count;
    }
}

// AbstractBeanDefinitionReader 184
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int count = 0;
    for (Resource resource : resources) {
        // reader 执行将配置文件读取为 BeanDefinition 并注册到 BeanFactory 的操作
        count += loadBeanDefinitions(resource);
    }
    return count;
}

// 这里终于到了 XmlBeanDefinitionReader 了
// XmlBeanDefinitionReader 309
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    // 将 resource 包装成一个 EncodedResource,可以解决(中文)乱码问题(之前手写IOC容器的时候就碰到过这个问题,当时使用的 URLDecoder,URLEncoder来解决乱码问题)
    // 调用重载
    return loadBeanDefinitions(new EncodedResource(resource));
}

// XmlBeanDefinitionReader 321
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Loading XML bean definitions from " + encodedResource);
    }

    Set currentResources = this.resourcesCurrentlyBeingLoaded.get();

    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
            "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }

    try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
        }
        // reader 真正执行将配置文件读取为 BeanDefinition 并注册到 BeanFactory 的操作
        // 这里的方法名加上了 do,重载了这么久,马上到了真正干事的地方了
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
            "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

上面我们一口气跟完了所有 loadBeanDefinitions 方法,但它们都没有做真正加载注册 BeanDefinition 的事。下面开始进入真正加载注册 BeanDefinition 的地方了。

// XmlBeanDefinitionReader 388
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {

    try {
        // 将 resource 转成 document
        document doc = doLoaddocument(inputSource, resource);
        // 根据 xml 配置文件读取 bean 信息注册 BeanDefinitions
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
    }
    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);
    }
}

// XmlBeanDefinitionReader 511
public int registerBeanDefinitions(document doc, Resource resource) throws BeanDefinitionStoreException {
    // 创建 BeanDefinitiondocumentReader, 类型: DefaultBeanDefinitiondocumentReader
    BeanDefinitiondocumentReader documentReader = createBeanDefinitiondocumentReader();
    
    // getRegistry 返回就是 IOC容器,也就是我们之前创建 DefaultListableBeanFactory
    // countBefore 容器原有 Bean 数量
    int countBefore = getRegistry().getBeanDefinitionCount();
    
    // doc: BeanDefinitiondocumentReader 实例
    // createReaderContext(resource): 返回 XmlReaderContext 实例
    // 调用 DefaultBeanDefinitiondocumentReader 的 registerBeanDefinitions 方法
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

// DefaultBeanDefinitiondocumentReader 94
public void registerBeanDefinitions(document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    // 传入dom树
    doRegisterBeanDefinitions(doc.getdocumentElement());
}

// DefaultBeanDefinitiondocumentReader 121
protected void doRegisterBeanDefinitions(Element root) {
    // 创建 BeanDefinition 解析器
    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.isDebugEnabled()) {
                    logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                 "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }
    // 前置处理,默认什么都不做,扩展点
    preProcessXml(root);
    // 真正解析 BeanDefinitions 的地方
    parseBeanDefinitions(root, this.delegate);
    // 后置处理,默认什么都不做,扩展点
    postProcessXml(root);

    this.delegate = parent;
}

到了这里,我们终于将xml配置文件转成了一棵dom树,后面将使用解析器来进行解析,生成BeanDefinition并注册到BeanFactory中。

// DefaultBeanDefinitiondocumentReader 170
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    // 解析默认标签    
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // 解析自定义标签,比如  ...
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

// 我们定义的是  
// 是走 parseDefaultElement,解析默认标签
// DefaultBeanDefinitiondocumentReader 193
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // 
    if (delegate.nodeNameEquals(ele, import_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    // 
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    // 
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    // 
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        doRegisterBeanDefinitions(ele);
    }
}

// 继续进入到解析的逻辑
// DefaultBeanDefinitiondocumentReader 310
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 读取 xml文件的 bean信息,创建 BeanDefinition;再通过beanName,beanDefinition和别名列表创建 BeanDefinitionHolder 并返回
    // BeanDefinitionHolder: 对读取的 BeanDefinition 信息的一个封装,里面包含 beanName,BeanDefinition,别名列表
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // 使用 BeanDefinitionReaderUtils 注册 BeanDefinition 信息
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
        }
        // 注册完成后发送事件
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

关键点:这个方法主要做了三个事情

将 bean 标签中的信息解析成一个 BeanDefinition 并包装成一个 BeanDefinitionHolder注册 BeanDefinition 到 BeanFactory 中注册完成发送事件

我们着重看前两个事情:

// 解析  信息成 BeanDefinitionHolder
// BeanDefinitionParserDelegate 414
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    // 将 name 属性按逗号,分号,空格切分成一个别名数组,如果 bean 没有配置 name,数组就为空
    List aliases = new ArrayList<>();
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }

    String beanName = id;
    // 如果没有配置 id,那么用别名的第一个作为 beanName
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        beanName = aliases.remove(0);
        if (logger.isTraceEnabled()) {
            logger.trace("No XML 'id' specified - using '" + beanName +
                         "' as bean name and " + aliases + " as aliases");
        }
    }

    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }

    // 根据  中的配置创建 BeanDefinition,然后把配置中的信息设置到 BeanDefinition 中
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            try {
                if (containingBean != null) {
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                        beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    beanName = this.readerContext.generateBeanName(beanDefinition);
                    String beanClassName = beanDefinition.getBeanClassName();
                    if (beanClassName != null &&
                        beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                        !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                        aliases.add(beanClassName);
                    }
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("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);
        // 返回 BeanDefinitionHolder
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}

// 我们跟进到生成 BeanDefinition 的逻辑中
// BeanDefinitionParserDelegate 503
public AbstractBeanDefinition parseBeanDefinitionElement(
    Element ele, String beanName, @Nullable BeanDefinition containingBean) {

    this.parseState.push(new BeanEntry(beanName));

    String className = null;
    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 {
        // 创建 BeanDefinition,设置类信息
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);

        // 设置 BeanDefinition 的一堆属性,这些属性定义在 AbstractBeanDefinition
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DEscriptION_ELEMENT));

        // 解析 
        parsemetaElements(ele, bd);
        // 解析 
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        // 解析 
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        // 解析 
        parseConstructorArgElements(ele, bd);
        // 解析 
        parsePropertyElements(ele, bd);
        // 解析 
        parseQualifierElements(ele, bd);

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

    return null;
}

下面是注册 bean 到 BeanFactory 中的逻辑,我们需要回到 DefaultBeanDefinitiondocumentReader 的 processBeanDefinition 方法。

// DefaultBeanDefinitiondocumentReader 310
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 读取 xml文件的 bean信息,创建 BeanDefinition;再通过beanName,beanDefinition和别名列表创建 BeanDefinitionHolder 并返回
    // BeanDefinitionHolder: 对读取的 BeanDefinition 信息的一个封装,里面包含 beanName,BeanDefinition,别名列表
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // 使用 BeanDefinitionReaderUtils 注册 BeanDefinition 信息
            // registry 就是之前创建 DefaultListableBeanFactory
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
        }
        // 注册完成后发送事件
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

// BeanDefinitionReaderUtils 158
public static void registerBeanDefinition(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    throws BeanDefinitionStoreException {
	// 获取 beanName
    String beanName = definitionHolder.getBeanName();
    // 注册 bean
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // 注册别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            // 存在一个 map 中, key -> value : alias -> beanName
            // 通过别名找 beanName,然后通过 beanName 找 bean
            registry.registerAlias(beanName, alias);
        }
    }
}

// 注册 beanName->beanDefinition 到 beanDefinitionMap 中
// 注册 beanName 到 beanDefinitionNames 中
// DefaultListableBeanFactory 958
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");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                   "Validation of bean definition failed", ex);
        }
    }

    // 获取容器中已经注册的 beanName 对应的 bean
    // 这里是处理之前说的 bean 覆盖的问题,我们还专门配置了“是否允许循环依赖"和"是否允许bean覆盖”这两个属性
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }
        else if (existingDefinition.getRole() < beanDefinition.getRole()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (logger.isInfoEnabled()) {
                logger.info("Overriding user-defined bean definition for bean '" + beanName +
                            "' with a framework-generated bean definition: replacing [" +
                            existingDefinition + "] with [" + beanDefinition + "]");
            }
        }
        else if (!beanDefinition.equals(existingDefinition)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Overriding bean definition for bean '" + beanName +
                             "' with a different definition: replacing [" + existingDefinition +
                             "] with [" + beanDefinition + "]");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Overriding bean definition for bean '" + beanName +
                             "' with an equivalent definition: replacing [" + existingDefinition +
                             "] with [" + beanDefinition + "]");
            }
        }
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        // 判断是否有其他 bean 已经初始化了
        if (hasBeanCreationStarted()) {
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                removeManualSingletonName(beanName);
            }
        }
        else {
            // 正常是进入到这个分支

            // beanDefinitionMap: 保存所有 beanName -> beanDefinition 的映射
            this.beanDefinitionMap.put(beanName, beanDefinition);
            
            // beanDefinitionNames: 保存所有的 beanName
            this.beanDefinitionNames.add(beanName);
            
            // manualSingletonNames: 这是个 linkedHashSet,保存手动注册的 singleton bean
            // 这里进行的容器自动加载 bean的操作,不是手动注册的,所以进行移除
            // 手动注册是指调用 registerSingleton(String beanName, Object singletonObject) 注册bean
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
    else if (isConfigurationFrozen()) {
        clearByTypeCache();
    }
}

到此,读取 xml 配置文件加载注册 beanDefinition 的操作就全部完成了。

我们再回到 refresh() 看看,现在我们已经分析完了 prepareRefresh() 和 obtainFreshBeanFactory()。

// AbstractApplicationContext 533
public void refresh() throws BeansException, IllegalStateException {
    // BeansException: 容器初始化失败,抛出此异常
    // IllegalStateException: 容器初始化完成后, 若再次进行 refresh, 抛出此异常

    // synchronized 保证线程安全性
    synchronized (this.startupShutdownMonitor) {
        // 设置启动时间,标志"启动"状态,验证标记为"需要"的配置文件都是可解析的,
        prepareRefresh();

        // ConfigurableListableBeanFactory接口: 继承了ConfigurableBeanFactory,ListableBeanFactory ,AutowireCapableBeanFactory三个接口
        // 重要!! 创建 BeanFactory(类型: DefaultListableFactory),读取 xml文件中定义的 bean信息为 beanDefinition,注册到 BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		
        prepareBeanFactory(beanFactory);

        try {
            // 到目前,所有 bean 的加载、注册都完成了,但是都还没有初始化
            // 扩展点: 子类可以在这里添加 BeanFactoryPostProcessor,做一些事情
            postProcessBeanFactory(beanFactory);

            // 调用各个 BeanFactoryPostProcessor 实现类的 postProcessBeanFactory(factory) 方法
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册所有 BeanPostProcessor
            // BeanPostProcessor 有两个方法,postProcessBeforeInitialization 和 postProcessAfterInitialization,这两个方法在 bean 初始化之前和之后执行
            // BeanPostProcessor 可以进行优先级排序
            registerBeanPostProcessors(beanFactory);

            // 初始化 ApplicationContext 的 MessageSource,国际化
            initMessageSource();

            // 初始化 ApplicationContext 的事件广播器
            initApplicationEventMulticaster();

            // 扩展点: 模板方法,可以在初始化特殊 bean 的时候调用
            onRefresh();

            // 注册事件监听器,监听器需要实现 ApplicationListener 接口
            registerListeners();

            // 初始化所有单例 Bean(标注了 lazy-init 的 bean 除外)
            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();
        }
    }
}
准备BeanFactory

接下来我们继续分析prepareBeanFactory()

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// 设置 BeanFactory 当前的类加载器(设置为当前 ApplicationContext 的类加载器)
	beanFactory.setBeanClassLoader(getClassLoader());
	if (!shouldIgnoreSpel) {
		beanFactory.setBeanexpressionResolver(new StandardBeanexpressionResolver(beanFactory.getBeanClassLoader()));
	}
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

	// 添加 ApplicationContextAwareProcessor
	// Aware 接口,在 bean 生命周期的初始化阶段,这个 processor 负责回调,将 ApplicationContext 注入到 bean 属性中
	// 注意:它不仅仅回调 ApplicationContextAware,还会负责回调 EnvironmentAware、ResourceLoaderAware 等
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

	// 如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
	// Spring 会通过其他方式来处理这些依赖。
	beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
	beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
	beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
	beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

	// 为几个特殊的 bean 赋值,如果 bean 依赖了下面几个,会注入相应的值
	// 每个 ApplicationContext 拥有一个 BeanFactory
	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
	// ApplicationContext 继承了 ResourceLoader、ApplicationEventPublisher、MessageSource,所以可以赋值为 this
	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
	beanFactory.registerResolvableDependency(ApplicationContext.class, this);

	// 在 bean 实例化后,如果是 ApplicationListener 的子类,
	// 那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	if (!IN_NATIVE_IMAGE && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}

	// 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
	if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
	}
	// 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
	if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
	}
	// 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
	if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
	}
}

在准备 BeanFactory 的过程中,Spring 主要是设置了 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册了几个特殊的 bean。

初始化所有单例Bean

本文的重中之重来了,初始化所有单例 bean。经过之前的分析,此时,BeanFactory 已经创建完成了,并且所有的实现了 BeanFactoryPostProcessor 接口的 Bean 都已经初始化并且其中的 postProcessBeanFactory(factory) 方法已经得到回调执行了。而且 Spring 已经“手动”注册了一些特殊的 Bean,如 environment、systemProperties 等。

下面就是初始化所有单例 bean。

Bean的生命周期

实例化对象 设置对象属性 检查Aware接口并设置相关依赖 BeanPostProcessor前置处理 InitializingBean接口 检查是否配置自定义的init-method BeanPostProcessor后置处理 DisposableBean接口和destroy方法 总结 参考资料
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号