Spring source analysis, 1: Preliminary Spring IOC core processes

This article describes the initialization process is substantially the IOC containers, listed only the more important processes and code, can be seen from the general process executed by the IOC container.

The next article will be more in-depth analysis of how Bean container parse xml, registration and initialization bean, as well as detailed process of how to obtain bean instances and so on.

Transfer: http://www.importnew.com/19243.html

1. Initialization

Roughly one-step process with the initialization at Spring IOC, the whole context is very large, the initialization process is mainly read XML resources, and resolve, final registration in the Bean Factory:

Upon completion of the initialization process, Bean were in the BeanFactory poised to be such as to call. Below with a specific example, to learn in detail about the initialization process, for example, when load following a bean:

<bean id="XiaoWang" class="com.springstudy.talentshow.SuperInstrumentalist">
    <property name="instruments">
        <list>
            <ref bean="piano"/>
            <ref bean="saxophone"/>
        </list>
    </property>
</bean>

Loading needs to be read, parsed, registration bean, which specific procedure call stack shown below:

The following detailed analysis of the key code for each step:

ready

Save the configuration position, and refresh
after calling ClassPathXmlApplicationContext, will save the configuration to the location information to configLocations, for use later resolved, then, it will call the AbstractApplicationContextrefresh method refreshes:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh,
        ApplicationContext parent) throws BeansException {
 
    super(parent);
    // 保存位置信息,比如`com/springstudy/talentshow/talent-show.xml`
    setConfigLocations(configLocations);
    if (refresh) {
        // 刷新
        refresh();
    }
}
 
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;
        }
    }
}

Creating loaded BeanFactory

protected final void refreshBeanFactory() throws BeansException {
    // ... ...
    DefaultListableBeanFactory beanFactory = createBeanFactory();
    // ... ...
    loadBeanDefinitions(beanFactory);
    // ... ...
}

Creating XMLBeanDefinitionReader

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
     throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    // ... ...
    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);

Read

Each process of creating a resource

public int loadBeanDefinitions(String location, Set<Resource> actualResources)
     throws BeanDefinitionStoreException {
    // ... ...
    // 通过Location来读取Resource
    Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
    int loadCount = loadBeanDefinitions(resources);
    // ... ...
}
 
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    for (Resource resource : resources) {
        // 载入每一个resource
        counter += loadBeanDefinitions(resource);
    }
    return counter;
}

XML processing each element

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // ... ...
    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)) {
                // 处理每个xml中的元素,可能是import、alias、bean
                parseDefaultElement(ele, delegate);
            }
            else {
                delegate.parseCustomElement(ele);
            }
        }
    }
    // ... ...
}

Resolution and registration bean

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 解析
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // 注册
            // Register the final decorated instance.
            BeanDefinitionReaderUtils.registerBeanDefinition(
                bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        // Send registration event.
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

In this step, by the elements of the XML parsing parseBeanDefinitionElement BeanDefinition is then present BeanDefinitionHolder, and then using the BeanDefinitionHolder BeanDefinition register, the essence is to put into BeanFactory BeanDefinition example, the detailed description and later resolution and registration process.

Resolve

Each processing element of Bean

public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, BeanDefinition containingBean) {
 
    // ... ...
    // 创建beandefinition
    AbstractBeanDefinition bd = createBeanDefinition(className, parent);
 
    parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
 
    parseMetaElements(ele, bd);
    parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    // 处理“Constructor”
    parseConstructorArgElements(ele, bd);
    // 处理“Preperty”
    parsePropertyElements(ele, bd);
    parseQualifierElements(ele, bd);
    // ... ...
}

Processing value of the property

public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
    String elementName = (propertyName != null) ?
                    "<property> element for property '" + propertyName + "'" :
                    "<constructor-arg> element";
 
    // ... ...
    if (hasRefAttribute) {
    // 处理引用
        String refName = ele.getAttribute(REF_ATTRIBUTE);
        if (!StringUtils.hasText(refName)) {
            error(elementName + " contains empty 'ref' attribute", ele);
        }
        RuntimeBeanReference ref = new RuntimeBeanReference(refName);
        ref.setSource(extractSource(ele));
        return ref;
    }
    else if (hasValueAttribute) {
    // 处理值
        TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
        valueHolder.setSource(extractSource(ele));
        return valueHolder;
    }
    else if (subElement != null) {
    // 处理子类型(比如list、map等)
        return parsePropertySubElement(subElement, bd);
    }
    // ... ...
}

1.4 Registration

public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {
 
    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
 
    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}
 
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {
 
    // ......
 
    // 将beanDefinition注册
    this.beanDefinitionMap.put(beanName, beanDefinition);
 
    // ......
}

The registration process, the core of the sentence is: this.beanDefinitionMap.put (beanName, beanDefinition), that is registered essence is to beanName is key, as with beanDefinition value, will put it into the HashMap.

registered

    public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {
 
    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
 
    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}
 
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {
 
    // ......
 
    // 将beanDefinition注册
    this.beanDefinitionMap.put(beanName, beanDefinition);
 
    // ......

Understanding the above two processes, we can achieve yourself a simple framework of Spring. So, I implemented a simple Simple Spring IOC framework according to their own understanding, are interested can look.

The registration process, the core of the sentence is: this.beanDefinitionMap.put(beanName, beanDefinition)that is the essence is registered with beanName is key, as with beanDefinition value, will put it into the HashMap.

Inject dependencies

Upon completion of the initialization IOC container, if not set bean lazy-init (lazy loading) attribute, then the instance of the bean will IOC after the initialization is completed in a timely manner initialized. Initialization will first create an instance, then according to the configuration of the example of further manipulation using the reflection, the specific flow is as follows:

Creation bean instance
is created bean instance procedure function call stack as follows:

Injection bean properties
injection procedure bean property function call stack shown below:

When you create a bean and bean injection properties, are carried out in doCreateBean function, we focus look:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,
            final Object[] args) {
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 创建bean的实例
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
     
        // ... ...
     
        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            // 初始化bean的实例,如注入属性
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
     
        // ... ...
    }

Understanding the above two processes, we can achieve yourself a simple framework of Spring. So, I implemented a simple framework of the IOC according to their own understanding of the Simple the Spring , are interested can look.

Guess you like

Origin www.cnblogs.com/xll1025/p/11407683.html