十三、Spring容器的原理及源码分析

1.Spring 容器相关的概念理解:
1)Spring的容器为ApplicationContext或BeanFactory(被称为IOC容器)
IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IOC容器进行组装。
在Spring中BeanFactory是IOC容器的实际代表者。
2)Spring IOC容器如何知道哪些是它管理的对象呢?
Spring IOC容器通过读取配置文件中的配置元数据,然后对元数据对应用中的各个对象进行实例化及装配。一般使用基于xml配置文件进行配置元数据,而且Spring与配置文件完全解耦的,可以使用其他任何可能的方式进行配置
元数据,比如注解、基于java文件的、基于属性文件的配置都可以。
3)Spring IOC容器管理的对象被称为Bean
Bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别。
疑问:IOC怎样确定如何实例化Bean、管理Bean之间的依赖关系以及管理Bean?简单说:这就需要配置元数据,带着这些疑问开始Spring容器的源码之旅吧.
2.IOC的实现原理就可以分为三个部分
1)通过代码解析xml这些配置文件,因为文件中包含<beans>,<bean>,<property>,<ref>,<value>,<list>等这样的标签内容,而<bean>标签中又有id/class等这样的属性;
2)创建“容器”,因为bean就是类实例化后存放在Spring容器中,所以这个容器需要Spring创建出来;
3)初始化bean
3.基本的初始化容器的代码示列:
public class SpringContainerApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context.xml");
OrderService orderService= context.getBean(OrderServiceImpl.class);
orderService.getOrderDetail();
//怎么样通过配置文件来启动 Spring 的 ApplicationContext,ApplicationContext 启动过程中,会负责创建实例 Bean,往各个 Bean 中注入依赖等
}
}
public class OrderServiceImpl implements OrderService {
@Override
public String getOrderDetail() {
System.out.println("订单查询执行完成!");
return "";
}
}
public interface OrderService {

String getOrderDetail();
}
4.根据3中容器初始化的代码 并结合如下类图及源码理解Spring容器原理

类图简单说明:

1)ApplicationContext(接口)容器继承了 ListableBeanFactory(接口),通过ListableBeanFactory 接口,我们可以获取多个 Bean,最顶层 BeanFactory 接口的方法都是获取单个Bean的。
2)ApplicationContext(接口)容器继承了 HierarchicalBeanFactory(接口),通过HierarchicalBeanFactory接口,我们可以获取父关系的bean、是否包含子bean
3)AutowireCapableBeanFactory(接口) 继承了BeanFactory(接口),它就是用来自动装配 Bean 用的。在 ApplicationContext 中通过方法 getAutowireCapableBeanFactory() 来使用它
这里的 BeanDefinition 就是我们所说的 Spring 的 Bean,我们自己定义的各个 Bean 其实会转换成一个个 BeanDefinition 存在于 Spring 的 BeanFactory 中 

步骤1:理解ClassPathXmlApplicationContext

 1 public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
 2 
 3     private Resource[] configResources;
 4     
 5     //创建一个新的ClassPathXmlApplicationContext,从给定的XML文件加载定义信息,并自动刷新上下文。
 6     public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
 7         this(new String[] {configLocation}, true, null);
 8     }
 9     
10     
11     public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
12             throws BeansException {
13         //Create a new AbstractXmlApplicationContext with the given parent context
14         //用已经有的 ApplicationContext 创建一个新的 AbstractXmlApplicationContext 并配置成父子关系
15         super(parent);
16 
17         //Set the config locations for this application context.
18         //解析xml配置文件列表,放置到成员变量 configResources 数组中
19         setConfigLocations(configLocations);
20 
21         if (refresh) {
22             //在ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法进行重建的,这样会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作
23             refresh();
24         }
25     }
26 
27 }    
View Code

步骤2:进入org.springframework.context.support.AbstractApplicationContext#refresh方法

@Override
    public void refresh() throws BeansException, IllegalStateException {
        //在销毁ApplicationContext 需要加锁,使用 synchronized 使用同步方法块锁定this.startupShutdownMonitor对象
        synchronized (this.startupShutdownMonitor) {
            // 刷新前准备:记录下容器的启动时间、标记启动状态、处理配置文件(properties文件)中的占位符
            prepareRefresh();
            
            /*
            这步完成后,配置文件就会解析成一个个BeanDefinition,注册到BeanFactory 中,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
            注册也只是将这些信息都保存到了注册中心(说到底核心是一个beanName->beanDefinition的map)
            */
            

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            //设置BeanFactory的类加载器:在初始化完成之后,修改应用程序上下文的内部bean工厂。所有bean定义都将被加载,但没有加载bean将被实例化。
            //这允许注册特殊某些ApplicationContext实现中的BeanPostProcessor等。
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //调用BeanFactoryPostProcessor各个实现类的 postProcessBeanFactory(factory) 方法
                invokeBeanFactoryPostProcessors(beanFactory);

                /*
                *Register bean processors that intercept bean creation.
                 首先:注册实现PriorityOrdered的beanPostProcessor;其次注册实现Ordered的BeanPostProcessor;最后,重新注册所有内部beanPostProcessor。
                */
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                // 初始化当前 ApplicationContext 的事件广播器
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //典型的模板方法(钩子方法),具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
                onRefresh();

                // Check for listener beans and register them.
                //注册事件监听器,监听器需要实现 ApplicationListener 接口
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //初始化所有的  singleton beans
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                // 最后,广播事件,ApplicationContext 初始化完成
                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.
                //销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
                destroyBeans();

                // Reset 'active' flag.
                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...
                resetCommonCaches();
            }
        }
    }
View Code

步骤2.1 obtainFreshBeanFactory()方法理解:

    public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {

        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            /*
            子类必须实现此方法才能执行实际的配置加载。在任何其他初始化工作之前,调用该方法。子类要么创建一个新的bean工厂并保存对它的引用,或者返回它持有的单个BeanFactory实例。
             在后一种情况下,如果多次刷新上下文,通常会引发IllegalStateException。
             关闭旧的 BeanFactory (如果有),创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
            */
            refreshBeanFactory();
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (logger.isDebugEnabled()) {
                logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
            }
            return beanFactory;
        }    
        
    }
View Code
    //org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
    public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

        @Override
        protected final void refreshBeanFactory() throws BeansException {
            //如果 ApplicationContext 中已经加载过 BeanFactory 了,销毁所有 Bean,关闭 BeanFactory。
            应用中 BeanFactory 本来就是可以多个的,这里可不是说应用全局是否有 BeanFactory,而是当前 ApplicationContext是否有 BeanFactory
            if (hasBeanFactory()) {
                destroyBeans();
                closeBeanFactory();
            }
            try {
                //初始化一个 DefaultListableBeanFactory
                DefaultListableBeanFactory beanFactory = createBeanFactory();
                //用于 BeanFactory 的序列化
                beanFactory.setSerializationId(getId());
                //设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
                customizeBeanFactory(beanFactory);
                //加载 BeanDefinition到 BeanFactory 中,但还不是真正的加载BeanDefinition,只是做准备
                loadBeanDefinitions(beanFactory);
                synchronized (this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }
            }
            catch (IOException ex) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
            }
        }
    }
View Code

        ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。
    以后所有的 BeanFactory 相关的操作其实是给这个实例来处理的。

//org.springframework.context.support.AbstractRefreshableApplicationContext#customizeBeanFactory
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            //是否允许 Bean 定义覆盖
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
            // 是否允许 Bean 间的循环依赖
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }
View Code
    org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        // 给这个 BeanFactory 实例化一个 XmlBeanDefinitionReader,来加载各个 Bean
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        // 初始化 BeanDefinitionReader,其实这个是提供给子类覆写的
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }
View Code
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    //默认只提供 sington 和 prototype 大家还知道的:request, session, globalSession, application, websocket 这几种属于基于 web 的扩展
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";
    int ROLE_APPLICATION = 0;
    int ROLE_SUPPORT = 1;
    int ROLE_INFRASTRUCTURE = 2;
    //获取父 Bean
    String getParentName();
    //设置父 Bean,这里涉及到 bean 继承,不是 java 继承
    void setParentName(String var1);
    //获取 Bean 的类名称
    String getBeanClassName();
    //设置 Bean 的类名称
    void setBeanClassName(String var1);
    //获取工厂名称
    String getFactoryBeanName();
    //如果该 Bean 采用工厂方法生成,指定工厂名称。
    void setFactoryBeanName(String var1);
    //获取工厂类中的 工厂方法名称
    String getFactoryMethodName();
    //指定工厂类中的 工厂方法名称
    void setFactoryMethodName(String var1);
    //获取 bean 的 scope
    String getScope();
    //设置 bean 的 scope
    void setScope(String var1);
    
    boolean isLazyInit();
    
    void setLazyInit(boolean var1);
    
    //返回该 Bean 的所有依赖
    String[] getDependsOn();
    
    //设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),而是 depends-on="" 属性设置的值
    void setDependsOn(String... var1);
    
    // 该 Bean 是否可以注入到其他 Bean 中
    boolean isAutowireCandidate();
    
    //设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效。如果根据名称注入,即使这边设置了 false,也是可以的
    void setAutowireCandidate(boolean var1);

    boolean isPrimary();

    void setPrimary(boolean var1);
    
    //获取构造器参数
    ConstructorArgumentValues getConstructorArgumentValues();

    //Bean 中的属性值,后面给 bean 注入属性值的时候会说到
    MutablePropertyValues getPropertyValues();

    boolean isSingleton();

    boolean isPrototype();
    
    //如果这个 Bean 原生是抽象类,那么不能实例化
    boolean isAbstract();

    int getRole();

    String getDescription();

    String getResourceDescription();

    BeanDefinition getOriginatingBeanDefinition();
}    
View Code

未完待续...

参看文章:

https://www.jianshu.com/p/2637e5b2acd1
https://www.cnblogs.com/deng-cc/p/6927447.html idea 查看类的继承关系图
原文地址:https://www.cnblogs.com/jiarui-zjb/p/13606728.html