spring源碼學習_bean工廠的初始化

spring framework的ioc容器可以讓我們輕鬆的用各種註解申明bean,並可以使用@Autowired進行依賴注入。本文我們就深入瞭解一下spring bean工廠的初始化過程,以及依賴注入的原理。

使用spring時,我們通常這樣創建一個spring的上下文

ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

AnnotationConfigApplicationContext類,及其構造方法

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

    //這是一個讀取器,用來讀取被註解標註的bean的信息
    private final AnnotatedBeanDefinitionReader reader;
    //這是一個掃描器,用於掃描路徑下的被註解標註的bean
    private final ClassPathBeanDefinitionScanner scanner;

    .....

    //初始化讀取器和掃描器
    public AnnotationConfigApplicationContext() {
        //這裏會先調用父類的無參構造方法,創建了一個默認的BeanFactory:DefaultListableBeanFactory
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        //先初始化讀取器和掃描器
        this();
        //這裏最終調用了讀取器的 register()方法,註冊給定的annotatedClasses
        register(annotatedClasses);
        //刷新上下文
        refresh();
    }
    ....
}

這裏可以看到,在創建spring的上下文時,首先生成了一個默認的 bean工廠,以及初始化了一個用來註冊bean的讀取器和一個用來掃描bean的掃描器。然後讓讀取器對給定的 annotatedClasses進行註冊,最後對上下文進行刷新操作。

1. register(Class<?>... annotatedClasses) 方法

這裏首先引入一個 spring的組件,叫做 BeanDefinition。如同Object對象一樣,Object是用來描述所有類的公共屬性以及公共功能的。BeanDefinition是spring用來描述所有bean的公共屬性以及功能的。比如 bean是否是懶加載,以及bean是否是單例的,這些有關bean的信息都被封裝在BeanDefinition中。

接下來看看 register方法,這個方法最終調用了AnnotatedBeanDefinitionReader的doRegisterBean方法

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

        //這裏就通過讀取bean的信息生成了一個 beanDefinition
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        //我們對bean進行的條件判斷@Conditional在這裏生效
        //這裏首先通過getMetadata方法拿到bean的註解信息,然後判斷@Conditional中的條件
        //對於不滿足條件的bean進行跳過,不註冊
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }
        //設置創建bean實例的一個回調
        abd.setInstanceSupplier(instanceSupplier);
        //解析並設置bean的作用域,默認爲singleton
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        //生成 beanName
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
        //解析並設置一些通用的註解信息
        //包括Lazy,Primary,DependsOn,Role和Description
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        //處理特殊限定符
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }
        //生成了一個bean的持有者,這個持有者包含了這個bean的 beanDefinition和 beanName,以及這個bean的別名。
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        //生成一個代理對象
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        //將我們的beanDefinition註冊到bean工廠的 beanDefinitionMap 中
        //DefaultListableBeanFactory內部維護一個Map<String, BeanDefinition>類型變量 beanDefinitionMap
        //所有被註冊的bean都會預先被裝入這個map中,等待進一步的處理
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

總的來看,register方法的作用就是讀取給定bean的註解信息,生成一個beanDefinition對象,並將這個對象註冊到bean工廠的beanDefinitionMap屬性中,等待下一步的處理。

 

2.refresh()方法

這個是spring上下文初始化時的核心方法,代碼如下

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);

				// 執行所有的BeanFactoryPostProcessors,這裏是重點,下面細講
				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();

				// 這裏初始化所有的剩下的非懶加載的單例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();
			}
		}
	}

這個方法進行了很多步驟,我們這裏重點說說裏面的兩個方法 invokeBeanFactoryPostProcessors和 finishBeanFactoryInitialization方法。

 

2.1 invokeBeanFactoryPostProcessors

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        //getBeanFactoryPostProcessors:拿到當前應用上下文beanFactoryPostProcessors變量中的值
        //invokeBeanFactoryPostProcessors:實例化並執行已經註冊的BeanFactoryPostProcessor
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

這裏引入spring的另一個組件:BeanFactoryPostProcessors(bean工廠的後置處理器)。到目前爲止,bean工廠已經實例化,被註冊的bean被放在beanDefinitionMap屬性中,等待被實例化。  BeanFactoryPostProcessors就是在 bean工廠實例化之後,bean實例化之前執行。

由於PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors這個方法的實現比較繁瑣,這裏我們挑重點的說

//先找到已經註冊的所有的實現了BeanDefinitionRegistryPostProcessor接口的bean
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}
//排序
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
//執行後置處理器
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

這裏獲取到所有已經註冊了並實現了BeanDefinitionRegistryPostProcessor接口的後置處理器,然後將其執行。

通過斷點我們發現,到目前爲止,我們的beanDefinitionMap中只存放了我們手動註冊的bean,以及spring爲我們內置的六個bean。

然而符合我們條件的bean就只有一個:ConfigurationClassPostProcessor。

也就是說,在我們沒有自定義後置處理器時,這裏只會執行ConfigurationClassPostProcessor,也可叫做配置類後置處理器。這個後置處理器的主要功能是 找到已經註冊的配置類,並將其解析執行。我們大名鼎鼎的@Componentscan註解就會在這裏發揮作用,其他在掃描範圍內的spring組件將會在這裏被註冊進beanDefinitionMap。

 

2.2 finishBeanFactoryInitialization

上面有說到,所有剩下的非懶加載的bean在這裏被實例化,finishBeanFactoryInitialization方法調用了beanFactory的preInstantiateSingletons方法進行bean的實例化。

    public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

       //這裏獲取到所有的beanName
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            //遍歷beanName 獲取所有bean的BeanDefinition
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            //只有當這bean 不是抽象類,並且是單例,非懶加載的,才實例化這個bean
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //工廠bean在這裏被實例化
                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);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        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();
                }
            }
        }
    }

當工廠中的bean被實例化完成後,bean工廠的初始化工作就已經完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章