2-Spring 容器建立

LZC發表於2020-03-28

重要類

BeanFactoryorg.springframework.beans.factory.BeanFactory,是一個非常純粹的 bean 容器,它是 IoC 必備的資料結構,其中 BeanDefinition 是它的基本結構。BeanFactory 內部維護著一個BeanDefinition map ,並可根據 BeanDefinition 的描述進行 bean 的建立和管理。

BeanDefinitionorg.springframework.beans.factory.config.BeanDefinition ,用來描述 Spring 中的 Bean 物件,如儲存物件的類路徑、物件的屬性。

ApplicationContextorg.springframework.context.ApplicationContext ,這個是 Spring 容器,它叫做應用上下文,與我們應用息息相關。

入口

// 建立ioc容器, sMainConfig為配置類
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
// AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
    // 讀取註解的Bean定義讀取器
    private final AnnotatedBeanDefinitionReader reader;
    // 掃描指定類路徑中註解Bean定義的掃描器
    private final ClassPathBeanDefinitionScanner scanner;
    // 無參建構函式
    public AnnotationConfigApplicationContext() {
        // 檢視new AnnotatedBeanDefinitionReader(this)原始碼可以發現
        // 此時往容器中注入了5個處理器
        // ConfigurationClassPostProcessor
        // AutowiredAnnotationBeanPostProcessor
        // CommonAnnotationBeanPostProcessor
        // EventListenerMethodProcessor
        // DefaultEventListenerFactory
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

    // 最常用的建構函式,透過將涉及的配置類傳遞給該建構函式,實現將相應配置類中的Bean自動註冊到容器中
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        // (1) 呼叫無參建構函式
        this();
        // (2) 將配置類資訊封裝成BeanDefinition物件儲存到beanDefinitionMap容器中
        register(annotatedClasses);
        // (3)重新整理容器,觸發容器對註解Bean的載入、解析和註冊
        refresh();
    }
}

第一步

呼叫無參建構函式往容器中注入五個處理器的作用

ConfigurationClassPostProcessorBeanFactoryPostProcessor的子類,

1.獲取配置類的@ComponentScan(basePackages = {"xxx.xxx.xxx"})資訊,將basePackages下的所有Bean註冊到容器中

2.獲取配置類中被@Bean註解標註的方法,並將這些Bean註冊到容器中

AutowiredAnnotationBeanPostProcessorBeanPostProcessor的子類

用來實現依賴注入的功能,在AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)方法中執行

CommonAnnotationBeanPostProcessor

EventListenerMethodProcessor:實現了SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor介面。收集容器中所有類中被@EventListener標註的方法,當有事件釋出時,這些被標註的方法會被執行。

@Service
public class UserService {
    @EventListener(classes = {ApplicationEvent.class})
    public void listener(ApplicationEvent event) {
        System.out.println("UserService..." + event);
    }
}

呼叫時機finishBeanFactoryInitialization(beanFactory),將所有的Bean例項化之後,遍歷所有的Bean,判斷Bean是否實現了SmartInitializingSingleton介面,如果實現了,那麼將呼叫SmartInitializingSingleton#afterSingletonsInstantiated()方法,該方法用來收集容器中被@EventListener標註的方法,將這些方法封裝成一個ApplicationListener註冊到容器中,context.addApplicationListener(applicationListener)

DefaultEventListenerFactory

將類中的某個方法轉換成ApplicationListener型別

第二步

將配置類資訊封裝成BeanDefinition物件儲存到beanDefinitionMap容器中

第三步

重新整理容器,觸發容器對註解Bean的載入、解析和註冊

// AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 重新整理前的預處理
        prepareRefresh();
        // 獲取一個BeanFactory(DefaultListableBeanFactory), 
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 2. BeanFactory 的預準備
        prepareBeanFactory(beanFactory);
        try {
            // 3. BeanFactory準備完成後的後置處理
            postProcessBeanFactory(beanFactory);
            // 4. 執行BeanFactoryPostProcessors的方法
            invokeBeanFactoryPostProcessors(beanFactory);
            // 5. 收集所有的 BeanPostProcessors
            registerBeanPostProcessors(beanFactory);
            // 6. 初始化上下文中的資原始檔,如國際化檔案的處理等
            initMessageSource();
            // 7. 初始化上下文事件廣播器
            initApplicationEventMulticaster();
            // 8.給子類擴充套件初始化其他Bean
            onRefresh();
            // 9. 在所有 bean 中查詢 listener bean,然後註冊到廣播器中
            registerListeners();
            // 10.初始化剩下的單例Bean(非延遲載入的)
            finishBeanFactoryInitialization(beanFactory);
            // 11. 完成重新整理過程,通知生命週期處理器 lifecycleProcessor 重新整理過程,同時發出 ContextRefreshEvent 通知別人
            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();
        }
    }
}

1.prepareRefresh();

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();
    // Validate that all properties marked as required are resolvable
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();
    // 儲存容器中的一些早期的事件
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

2.prepareBeanFactory(beanFactory);

BeanFactory 的預準備

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 設定BeanFactory的類載入器、支援表示式解析的.
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 新增一個BeanPostProcessor
    // Bean初始化時(initializeBean)用來判斷是否實現了ApplicationContextAware、MessageSourceAware等介面
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 設定忽略自動裝配的介面, 不能透過介面型別來自動注入
    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中注入這些
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    // 新增一個BeanPostProcessor
    // Bean初始化時(initializeBean)收集實現了ApplicationListener的類
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    // // 增加對AspectJ的支援
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // 註冊一些預設的環境Bean
    // Register default environment beans.
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

3.postProcessBeanFactory(beanFactory);

BeanFactory準備完成後的後置處理。這是一個空方法,子類可以重寫這個方法。

4.invokeBeanFactoryPostProcessors(beanFactory);

透過beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)

beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)獲取實現了BeanDefinitionRegistryPostProcessors介面和BeanFactoryPostProcessors介面的類,獲取過程中會觸發Bean的例項化然後執行相應的方法。可以透過實現PriorityOrderedOrdered介面來實現優先順序。

先執行postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法,

然後執行postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

前面提到的ConfigurationClassPostProcessor類就是實現了BeanDefinitionRegistryPostProcessors介面,而BeanDefinitionRegistryPostProcessors繼承了BeanFactoryPostProcessors介面。這個類的作用如下:

1.獲取配置類的@ComponentScan(basePackages = {"xxx.xxx.xxx"})資訊,將basePackages下的所有Bean註冊到容器中

2.獲取配置類中被@Bean註解標註的方法,並將這些Bean註冊到容器中

這一步完成後,所有的Bean都已經註冊到容器中,此時只有實現了BeanFactoryPostProcessors的類被例項化了,其它Bean都還沒有例項化。透過實現BeanFactoryPostProcessors介面,我們可以修改BeanDefinition的一些屬性。

5.registerBeanPostProcessors(beanFactory);

獲取所有實現了BeanPostProcessor介面的類,並將這些類儲存在一個List列表裡面,以便後續使用。可以透過實現PriorityOrderedOrdered介面來實現優先順序。此時這些類也會被例項化。Bean初始化時(initializeBean),會執行這些類的postProcessBeforeInitialization(Object bean, String beanName)方法和postProcessAfterInitialization(Object bean, String beanName)

6.initMessageSource();

初始化上下文中的資原始檔,如國際化檔案的處理等 。判斷容器中是否存在id為messageSource並且型別是MessageSource的Bean,如果有則賦值給messageSource,如果沒有則自己建立一DelegatingMessageSource,並注入到容器中。 其實該方法就是初始化一個 MessageSource 介面的實現類,主要用於國際化/i18n。

7.initApplicationEventMulticaster();

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果存在 applicationEventMulticaster bean,則獲取賦值
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        // 沒有則新建 SimpleApplicationEventMulticaster,並完成 bean 的註冊
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                         "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}

如果當前容器中存在 applicationEventMulticaster 的 bean,則對 applicationEventMulticaster 賦值,否則新建一個 SimpleApplicationEventMulticaster 的物件(預設的),並完成註冊。

8.onRefresh();

預留給 AbstractApplicationContext 的子類用於初始化其他特殊的 bean,該方法需要在所有單例 bean 初始化之前呼叫。 例如在SpringBoot裡面,ServletWebServerApplicationContext實現了這個方法,在這個方法裡面開始啟動web應用伺服器,如Tomcat。

9.registerListeners();

protected void registerListeners() {
    // 首先註冊指定的靜態監聽器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 獲取所有ApplicationListener型別的Bean名字然後註冊到ApplicationEventMulticaster
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 下面將釋出前期的事件給監聽器
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

10.finishBeanFactoryInitialization(beanFactory);

初始化剩下的單例Bean(非延遲載入的)

// AbstractApplicationContext
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // ....省略前面的方法
    // 初始化剩下的單例Bean(非延遲載入的)
    beanFactory.preInstantiateSingletons();
}

最終呼叫如下方法

// DefaultListableBeanFactory
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }
    // 獲取所有的bean名字
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // 觸發所有單例的、非懶載入的Bean的例項化
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    final FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                                                    ((SmartFactoryBean<?>) factory)::isEagerInit,
                                                                    getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                       ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName); // 此時會觸發Bean的例項化
                    }
                }
            }
            else {
                getBean(beanName); // 此時會觸發Bean的例項化
            }
        }
    }

    // 所有單例的、非懶載入的Bean已經全部例項化
    // 收集容器中被@EventListener標註的方法,將這些方法封裝成一個ApplicationListener註冊到容器中
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

11.finishRefresh()

完成重新整理過程,通知生命週期處理器 LifecycleProcessor 重新整理過程,同時發出 ContextRefreshEvent 通知別人

protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    clearResourceCaches();
    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();
    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();
    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));
    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}

這個時候IOC容器就建立完成了。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章