2 IOC与DI

2018-09-28  本文已影响0人  十丈_红尘
1️⃣IOC与DI是什么?
  1. IOC称之为反转控制 : 反转资源获取的方向,可以理解为查找的被动形式.
  2. DI 称之为依赖注入 : 通过预定好的方式(set方法、构造器)来接收容器推送的资源.可以理解为 IOC是思想,而DI是IOC的具体的实现.

2️⃣Spring源码解析 : 容器的创建以及Bean初始化

创建测试用例并使用debug启动

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestIOC {

    @Test
    public void test() {
        // 查看IOC容器的创建细节
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        Object bean = ioc.getBean("person01");
        System.out.println(bean);
    }
}
  1. ClassPathXmlApplicationContext的创建
    /**
     * Create a new ClassPathXmlApplicationContext, loading the definitions
     * from the given XML file and automatically refreshing the context.
     * @param configLocation resource location
     * @throws BeansException if context creation failed
     */
    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }
  1. this的实现
    /**
     * Create a new ClassPathXmlApplicationContext with the given parent,
     * loading the definitions from the given XML files.
     * @param configLocations array of resource locations
     * @param refresh whether to automatically refresh the context,
     * loading all bean definitions and creating all singletons.
     * Alternatively, call refresh manually after further configuring the context.
     * @param parent the parent context
     * @throws BeansException if context creation failed
     * @see #refresh()
     */
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
                        // 刷新ioc容器,启动和创建bean
            refresh();
        }
    }
  1. 解析配置文件
/**
     * Set the config locations for this application context.
     * <p>If not set, the implementation may use a default as appropriate.
     */
    public void setConfigLocations(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++) {
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }
  1. 进入refresh() : AbstractApplicationContext IOC容器的启动和Bean的创建都在这个方法中,里边调用了很多的方法.

    继承关系
@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

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

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

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

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

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

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }
  1. prepareRefresh() : 刷新容器
  1. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();这个其实就是一个工厂,Spring是利用工厂创建Bean的

    工厂在解析XML文件的时候,解析完成以后会保存每一个要创建的bean的详细信息,至此并未创建bean;



    这个map保存解析后的每一个bean的配置信息,创建bean就是按照配置信息创建的;
  1. prepareBeanFactory(beanFactory);做一些准备工作;
  1. postProcessBeanFactory(beanFactory);暂时没有深入研究这个;
  1. invokeBeanFactoryPostProcessors(beanFactory);执行后置处理器;
  1. registerBeanPostProcessors(beanFactory);注册bean的后置处理器;
  1. initMessageSource();初始化消息源;
  1. initApplicationEventMulticaster();初始化事件转发器;
  1. onRefresh();这是一个让子类自己实现的空方法;
  1. registerListeners();注册监听器;
  1. finishBeanFactoryInitialization(beanFactory);完成bean的初始化工作;

    初始化所有的单实例bean; 进入此方法观察bean的创建细节;
  1. finishRefresh();完成刷新;
上一篇 下一篇

猜你喜欢

热点阅读