Spring-IOC

容器概述

控制反轉(zhuǎn)(IoC)也稱為依賴注入(DI),它是一個(gè)過(guò)程。對(duì)象(Bean)通過(guò)構(gòu)造方法、工廠方法、屬性設(shè)置依賴項(xiàng),然后容器在創(chuàng)建對(duì)象(Bean)時(shí),注入這些依賴項(xiàng)。此過(guò)程從根本上說(shuō)是通過(guò)設(shè)置的依賴項(xiàng)去查找對(duì)象(Bean)而不是我們主動(dòng)去設(shè)置(因此稱為控制翻轉(zhuǎn))。

IOC概述.png

IOC容器

BeanFactory

  • org.springframework.beans中默認(rèn)實(shí)現(xiàn)DefaultListableBeanFactory類圖


    DefaultListableBeanFactory類圖.png

ApplicationContext

  • 類圖


    ApplicationContext類圖.png

Environment

  • 來(lái)看下servlet的環(huán)境StandardServletEnvironment類圖


    StandardServletEnvironment類圖.png
  • Environment是在初始化時(shí)AbstractEnvironment調(diào)用鉤子方法customizePropertySources把對(duì)應(yīng)環(huán)境加進(jìn)去的,下面我們來(lái)看下相應(yīng)的代碼

    • AbstractEnvironment
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
     ......
    /**
     * Create a new {@code Environment} instance, calling back to
     * {@link #customizePropertySources(MutablePropertySources)} during construction to
     * allow subclasses to contribute or manipulate {@link PropertySource} instances as
     * appropriate.
     * @see #customizePropertySources(MutablePropertySources)
     */
    public AbstractEnvironment() {
        //初始化時(shí),子類添加環(huán)境
        customizePropertySources(this.propertySources);
    }
    protected void customizePropertySources(MutablePropertySources propertySources) {
    //空方法,子類需要添加環(huán)境時(shí)覆蓋
    }
    ......
}
  • StandardEnvironment
public class StandardEnvironment extends AbstractEnvironment {

    /** System environment property source name: {@value}. */
    public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";

    /** JVM system properties property source name: {@value}. */
    public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";


    /**
     * Customize the set of property sources with those appropriate for any standard
     * Java environment:
     * <ul>
     * <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME}
     * <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}
     * </ul>
     * <p>Properties present in {@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} will
     * take precedence over those in {@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}.
     * @see AbstractEnvironment#customizePropertySources(MutablePropertySources)
     * @see #getSystemProperties()
     * @see #getSystemEnvironment()
     */
    @Override
    protected void customizePropertySources(MutablePropertySources propertySources) {
        //添加JVM 環(huán)境變量,我們平時(shí)在idea和tomcat里面寫的-D參數(shù)
        propertySources.addLast(
                new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
        //電腦的環(huán)境變量
        propertySources.addLast(
                new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
    }

}
  • StandardServletEnvironment
public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
    @Override
    protected void customizePropertySources(MutablePropertySources propertySources) {
        ......
        // 添加servletConfigInitParams環(huán)境,web.xml里面寫的init-param
        propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
        // 添加servletContextInitParams環(huán)境,web.xml里面寫的context-param
        propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
        // 添加jndiProperties環(huán)境,配置數(shù)據(jù)庫(kù)的,一般寫在tomcat里面的resource
        if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
            propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
        }
        //調(diào)用父類,添加標(biāo)準(zhǔn)環(huán)境
        super.customizePropertySources(propertySources);
    }
    ......
}

統(tǒng)一資源加載策略

Resource

Java自帶的java.net.URL類不足以滿足所有對(duì)低級(jí)資源的訪問(wèn),比如沒(méi)有標(biāo)準(zhǔn)化的URL實(shí)現(xiàn)可用于訪問(wèn)需要從類路徑或相對(duì)于ServletContext獲得的資源。Spring的Resource接口旨在成為一種功能更強(qiáng)大的接口,用于抽象化對(duì)低級(jí)資源的訪問(wèn)。下面來(lái)看下幾個(gè)常用resource的類圖


resource類圖.png

ResourceLoader

ResourceLoader類圖.png
  • 返回多個(gè)資源的ResourcePatternResolver


    ResourcePatternResolver類圖.png

ApplicationContext分析

ClassPathXmlApplicationContext時(shí)序圖

  • 加載BeanDefinition時(shí)序圖


    xml加載BeanDefinition.png
  • 實(shí)例化時(shí)序圖


    實(shí)例會(huì).png

AbstractApplicationContext的refresh方法

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            // 裝備刷新方法,時(shí)間、環(huán)境、事件這些
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            // 告訴子類刷新BeanFactory,加載BeanDefinition,獲取最新的BeanFactory
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // 準(zhǔn)備BeanFactory,類加載器、忽略接口、屬性解析等
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 為某些子類預(yù)留的BeanFactory后置處理
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                // 執(zhí)行BeanFactoryPostProcessor后置處理
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 注冊(cè)掃描到的BeanPostProcessor到應(yīng)用上下文
                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.
                // 初始化所有剩余的單例bean
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                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.
                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();
            }
        }
    }

ApplicationContext擴(kuò)展點(diǎn)

FactoryBean

FactoryBean是實(shí)現(xiàn)了org.springframework.beans.factory.FactoryBean<T>接口的Bean,從ApplicationContext的getBean()方法獲取的對(duì)象不是該類的一個(gè)實(shí)例,而是該類的getObject()方法所返回的對(duì)象。
當(dāng)我們需要獲取FactoryBean實(shí)例本身而不是它所產(chǎn)生的bean,則要使用'&'符號(hào)。
當(dāng)有復(fù)雜的初始化場(chǎng)景,比如返回propertySource、mybatis的代理類

BeanFactoryPostProcess

當(dāng)BeanFactory加載完成BeanDefinition之后,對(duì)BeanDefinition的后置處理

BeanPostProcess

當(dāng)對(duì)象new出來(lái),在執(zhí)行init方法之前和之后執(zhí)行

public interface BeanPostProcessor {
    // init方法之前
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    
    // init方式之后
        @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容