之前两篇文章Spring源码分析:非懒加载的单例Bean初始化过程(上)Spring源码分析:非懒加载的单例Bean初始化过程(下)比较详细地分析了非懒加载的单例Bean的初始化过程,整个流程始于AbstractApplicationContext的refresh()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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;
        }
    }
}

之前重点分析的是finishBeanFactoryInitialization方法,这个方法完成了所有非懒加载的单例Bean的初始化。今天我回头重看了一下refresh()方法,发现前面有一些方法还是忽略了没有去特别在意,其实他们都是Spring整个启动流程中的重要组成部分,下面就来分析一下finishBeanFactoryInitialization方法前面的一些方法。

obtainFreshBeanFactory方法之前已经详细分析过了,就从prepareBeanFactory方法开始。

PrepareBeanFactory方法

看一下PrepareBeanFactory方法的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
 
    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
 
    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
 
    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    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()));
    }
 
    // Register default environment beans.
    if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        Map systemProperties;
        try {
            systemProperties = System.getProperties();
        }
        catch (AccessControlException ex) {
            systemProperties = new ReadOnlySystemAttributesMap() {
                @Override
                protected String getSystemAttribute(String propertyName) {
                    try {
                        return System.getProperty(propertyName);
                    }
                    catch (AccessControlException ex) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Not allowed to obtain system property [" + propertyName + "]: " +
                                    ex.getMessage());
                        }
                        return null;
                    }
                }
            };
        }
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
    }
 
    if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        Map<String,String> systemEnvironment;
        try {
            systemEnvironment = System.getenv();
        }
        catch (AccessControlException ex) {
            systemEnvironment = new ReadOnlySystemAttributesMap() {
                @Override
                protected String getSystemAttribute(String variableName) {
                    try {
                        return System.getenv(variableName);
                    }
                    catch (AccessControlException ex) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +
                                    ex.getMessage());
                        }
                        return null;
                    }
                }
            };
        }
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
    }
}

首先是第3行,配置当前上下文ClassLoader

接着是第4行,这是一个表达是语言处理器,可以使用#{bean.xxx}的方式来调用相关属性值

接着是第5行,这是一个属性编辑器,具体没怎么用过

接着是第8行,第8行增加了一个ApplicationContextAwareProcessor用于上下文回调,它是BeanPostProcessor的实现类,跟一下这个接口的两个方法postProcessBeforeInitialization和postProcessAfterInitialization即可知道这个方法的作用是:

  • 如果Bean是EmbeddedValueResolverAware接口的实现类,则调用setEmbeddedValueResolver方法,传入当前BeanFactory
  • 如果Bean是ResourceLoaderAware接口的实现类,则调用setResourceLoader方法,传入当前上下文ApplicationContext
  • 如果Bean是ApplicationEventPublisherAware的实现类,则调用setApplicationEventPublisher方法,传入当前上下文ApplicationContext
  • 如果Bean是MessageSourceAware的实现类,则调用setMessageSource方法,传入当前上下文ApplicationContext
  • 如果Bean是ApplicationContextAware的实现类,则调用setApplicationContext方法,传入当前上下文ApplicationContext

接着是第9行~第12行,意思是Bean如果是这些接口的实现类,则不会被自动装配,自动装配见【Spring9】Autowire(自动装配)机制

接着是第16行~第19行,意思是修正依赖,这里是一些自动装配的特殊规则,比如是BeanFactory接口的实现类,则修正为当前BeanFactory

接着是第22行~第26行,意思是如果自定义的Bean中没有一个名为”loadTimeWeaver”的Bena,则会添加一个LoadTimeWeaverAwareProcessor

最后是第29行~第77行,意思是如果自定义的Bean中没有名为”systemProperties”和”systemEnvironment”的Bean,则注册两个Bena,Key为”systemProperties”和”systemEnvironment”,Value为Map,这两个Bean就是一些系统配置和系统环境信息,具体可以写这么一段代码测试一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TestSpring {
 
    @SuppressWarnings("unchecked")
    @Test
    public void testSpring() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring/spring.xml");
 
        Map<String, String> systemPropertiesBean = (Map<String, String>)ac.getBean("systemProperties");
        for (Map.Entry<String, String> entry : systemPropertiesBean.entrySet()) {
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
 
        System.out.println("==============================华丽的分隔符==============================");
        Map<String, String> systemEnvironmentBean = (Map<String, String>)ac.getBean("systemEnvironment");
        for (Map.Entry<String, String> entry : systemEnvironmentBean.entrySet()) {
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
    }
 
}

涉及个人信息,运行结果我就不贴了,大家可以自己试试,至此整个PrepareBeanFactory方法的细节已经分析完毕了。

invokeBeanFactoryPostProcessors方法

这个是整个Spring流程中非常重要的一部分,是Spring留给用户的一个非常有用的扩展点,BeanPostProcessor接口针对的是每个Bean初始化前后做的操作而BeanFactoryPostProcessor接口针对的是所有Bean实例化前的操作,注意用词,初始化只是实例化的一部分,表示的是调用Bean的初始化方法,BeanFactoryPostProcessor接口方法调用时机是任意一个自定义的Bean被反射生成出来前

OK,看一下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<String>();
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
        List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
                new LinkedList<BeanDefinitionRegistryPostProcessor>();
        for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryPostProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryPostProcessors.add(registryPostProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }
        Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
                beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
        List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
                new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
        OrderComparator.sort(registryPostProcessorBeans);
        for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
        invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        processedBeans.addAll(beanMap.keySet());
    }
    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
    }
 
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
 
    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
 
    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    OrderComparator.sort(priorityOrderedPostProcessors);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
 
    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    OrderComparator.sort(orderedPostProcessors);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
 
    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
}

我们可以自己实现BeanFactoryPostProcessor接口并实现postProcessBeanFactory方法,在所有Bean加载的流程开始前,会调用一次postProcessBeanFactory方法。分析一下这段代码,首先我们使用的是DefaultListableBeanFactory,它是BeanDefinitionRegistry的子类,因此进入第4行的判断。

整个判断获取的是当前有的BeanFactoryPostProcessor并调用postProcessBeanFactory,这些BeanFactoryPostProcessor是前置通过AbstractApplicationContext的addBeanFactoryPostProcessor方法添加的而不是配置文件里面配置的BeanFactoryPostProcessor的实现Bean,因此这个判断没有任何可执行的BeanFactoryPostProcessor。

接着40行~41行这两行,获取的是beanDefinitionMap中的Bean,即用户自定义的Bean。

接着第45行~61行,这里分出了三个List,表示开发者可以自定义BeanFactoryPostProcessor的调用顺序,具体为调用顺序为:

  • 如果BeanFactoryPostProcessor实现了PriorityOrdered接口(PriorityOrdered接口是Ordered的子接口,没有自己的接口方法定义,只是做一个标记,表示调用优先级高于Ordered接口的子接口),是优先级最高的调用,调用顺序是按照接口方法getOrder()的实现,对返回的int值从小到大进行排序,进行调用
  • 如果BeanFactoryPostProcessor实现了Ordered接口,是优先级次高的调用,将在所有实现PriorityOrdered接口的BeanFactoryPostProcessor调用完毕之后,依据getOrder()的实现对返回的int值从小到大排序,进行调用
  • 不实现Ordered接口的BeanFactoryPostProcessor在上面的BeanFactoryPostProcessor调用全部完毕之后进行调用,调用顺序就是Bean定义的顺序

最后的第63行~第80行就是按照上面的规则依次调用BeanFactoryPostProcessor的postProcessBeanFactory方法。

registerBeanPostProcessors方法

接下来看看registerBeanPostProcessors方法,顾名思义,就是注册自定义的BeanPostProcessor接口。看一下代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
 
    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
 
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {
        if (isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
 
    // First, register the BeanPostProcessors that implement PriorityOrdered.
    OrderComparator.sort(priorityOrderedPostProcessors);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
 
    // Next, register the BeanPostProcessors that implement Ordered.
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    OrderComparator.sort(orderedPostProcessors);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
 
    // Now, register all regular BeanPostProcessors.
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
 
    // Finally, re-register all internal BeanPostProcessors.
    OrderComparator.sort(internalPostProcessors);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
 
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector());
}

整体代码思路和invokeBeanFactoryPostProcessors方法类似,但是这里不会调用BeanPostProcessor接口的方法,而是把每一个BeanPostProcessor按照顺序放入一个List中,到时候按顺序调用。

具体代码思路可以参考invokeBeanFactoryPostProcessors,这里就根据代码总结一下BeanPostProcessor接口的调用顺序:

  • 优先调用PriorityOrdered接口的子接口,调用顺序依照接口方法getOrder的返回值从小到大排序
  • 其次调用Ordered接口的子接口,调用顺序依照接口方法getOrder的返回值从小到大排序
  • 接着按照BeanPostProcessor实现类在配置文件中定义的顺序进行调用
  • 最后调用MergedBeanDefinitionPostProcessor接口的实现Bean,同样按照在配置文件中定义的顺序进行调用

initMessageSource方法

initMessageSource方法用于初始化MessageSource,MessageSource是Spring定义的用于实现访问国际化的接口,看一下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // Make MessageSource aware of parent MessageSource.
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // Only set parent context as parent MessageSource if no parent MessageSource
                // registered already.
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // Use empty MessageSource to be able to accept getMessage calls.
        DelegatingMessageSource dms = new DelegatingMessageSource();
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                    "': using default [" + this.messageSource + "]");
        }
    }
}

这个if…else…判断比较好理解:

  • 如果自定义了名为”messageSource”的Bean,那么直接实例化Bean,该Bean必须是MessageSource接口的实现Bean,顺便该Bean如果是HierarchicalMessageSource接口的实现类,强转为HierarchicalMessageSource接口,并设置一下parentMessageSource
  • 如果没有自定义名为”messageSource”的Bean,那么会默认注册一个DelegatingMessageSource并加入

initApplicationEventMulticaster方法

initApplicationEventMulticaster方法是用于初始化上下文事件广播器的,看一下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                    APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                    "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

和initMessageSource方法一样,这个if…else…判断也比较好理解:

  • 如果自定义了名为”applicationEventMulticaster”的Bean,就实例化自定义的Bean,但自定义的Bean必须是ApplicationEventMulticaster接口的实现类
  • 如果没有自定义名为”ApplicationEventMulticaster”的Bean,那么就注册一个类型为SimpleApplicationEventMulticaster的Bean

整个Spring的广播器是观察者模式的经典应用场景之一,这个之后有时间会分析Spring广播器的源码。

onRefresh方法

接下来简单说说onRefresh方法,AbstractApplicationContext中这个方法没有什么定义:

1
2
3
4
5
6
7
8
9
10
/**
 * Template method which can be overridden to add context-specific refresh work.
 * Called on initialization of special beans, before instantiation of singletons.
 * <p>This implementation is empty.
 * @throws BeansException in case of errors
 * @see #refresh()
 */
protected void onRefresh() throws BeansException {
    // For subclasses: do nothing by default.
}

看一下注释的意思:一个模板方法,重写它的作用是添加特殊上下文刷新的工作,在特殊Bean的初始化时、初始化之前被调用。在Spring中,AbstractRefreshableWebApplicationContext、GenericWebApplicationContext、StaticWebApplicationContext都实现了这个方法。

registerListeners方法

registerListeners方法顾名思义,用于注册监听器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * Add beans that implement ApplicationListener as listeners.
 * Doesn't affect other listeners, which can be added without being beans.
 */
protected void registerListeners() {
    // Register statically specified listeners first.
    for (ApplicationListener listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String lisName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(lisName);
    }
}

这里先向applicationEventMulticaster中注册一些静态的、特定的监听器。

finishRefresh方法

最后一步,结束Spring上下文刷新:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * Finish the refresh of this context, invoking the LifecycleProcessor's
 * onRefresh() method and publishing the
 * {@link org.springframework.context.event.ContextRefreshedEvent}.
 */
protected void finishRefresh() {
    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();
 
    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();
 
    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));
}

这里面分了三步,第一步,初始化LifecycleProcessor接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        this.lifecycleProcessor =
                beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
        }
    }
    else {
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate LifecycleProcessor with name '" +
                    LIFECYCLE_PROCESSOR_BEAN_NAME +
                    "': using default [" + this.lifecycleProcessor + "]");
        }
    }
}

流程和initMessageSource方法、initApplicationEventMulticaster方法基本类似:

  • 先找一下有没有自定义名为”lifecycleProcessor”的Bean,有的话就实例化出来,该Bean必须是LifecycleProcessor的实现类
  • 没有自定义名为”lifecycleProcessor”的Bean,向Spring上下文中注册一个类型为DefaultLifecycleProcessor的LifecycleProcessor实现类

第二步,调用一下LifecycleProcessor的onRefresh方法。

第三步,由于之前已经初始化了:

1
2
3
4
5
6
7
8
9
10
public void publishEvent(ApplicationEvent event) {
    Assert.notNull(event, "Event must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Publishing event in " + getDisplayName() + ": " + event);
    }
    getApplicationEventMulticaster().multicastEvent(event);
    if (this.parent != null) {
        this.parent.publishEvent(event);
    }
}

后记

再看AbstractApplicationContext的refresh方法,从中读到了很多细节:

  • Spring默认加载的两个Bean,systemProperties和systemEnvironment,分别用于获取环境信息、系统信息
  • BeanFactoryPostProcessor接口用于在所有Bean实例化之前调用一次postProcessBeanFactory
  • 可以通过实现PriorityOrder、Order接口控制BeanFactoryPostProcessor调用顺序
  • 可以通过实现PriorityOrder、Order接口控制BeanPostProcessor调用顺序
  • 默认的MessageSource,名为”messageSource”
  • 默认的ApplicationEventMulticaster,名为”applicationEventMulticaster”
  • 默认的LifecycleProcessor,名为”lifecycleProcessor”

除了这些,在整个refresh方法里还隐藏了许多细节,这里就不一一罗列了,多读源码,会帮助我们更好地使用Spring。

Spring源码分析:非懒加载的单例Bean初始化前后的一些操作的更多相关文章

  1. 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作

    前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...

  2. 【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)

    doCreateBean方法 上文[Spring源码分析]非懒加载的单例Bean初始化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下 ...

  3. Spring源码分析:非懒加载的单例Bean初始化过程(下)

    上文Spring源码分析:非懒加载的单例Bean初始化过程(上),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireC ...

  4. 【Spring源码分析】非懒加载的单例Bean初始化过程(上篇)

    代码入口 上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了f ...

  5. Spring源码分析:非懒加载的单例Bean初始化过程(上)

    上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了finish ...

  6. Spring源码分析(十五)获取单例

    本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例be ...

  7. Spring源码剖析4:懒加载的单例Bean获取过程分析

    本文转自五月的仓颉 https://www.cnblogs.com/xrq730 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https ...

  8. 【Spring源码分析系列】加载Bean

    /** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * ...

  9. 从SpringBoot源码分析 配置文件的加载原理和优先级

    本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级     跟入源码之前,先提一个问题:   SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数( ...

随机推荐

  1. SSO集成方案[随笔]

    看这个方案之前,先说明下为什么要加入SSO,以防对大家产生不好的影响.我们产品使用传统winform+db服务+Db存储方式开发,一群老菜帮子开发,以传统的datatble做数据传递,很多年了未有变化 ...

  2. 在Asp.Net MVC中利用快递100接口实现订阅物流轨迹功能

    前言 分享一篇关于在电商系统中同步物流轨迹到本地服务器的文章,当前方案使用了快递100做为数据来源接口,这个接口是收费的,不过提供的功能还是非常强大的,有专门的售后维护团队.也有免费的方案,类似于快递 ...

  3. IE浏览器兼容性模式

    最近支持公司的一个内部业务管理系统,系统是基于jQuery来实现:用了2年的MVVM框架的我转向这个完全使用jQuery框架来开发的系统,真是相当不爽(相信用过MVVM框架的跟我是相同的感受):更为憋 ...

  4. 【BZOJ1052】 [HAOI2007]覆盖问题

    BZOJ1052 [HAOI2007]覆盖问题 前言 小清新思维题. 最近肯定需要一些思维题挽救我这种碰到题目只会模板的菜鸡. 这题腾空出世? Solution 考虑一下我们二分答案怎么做? 首先转换 ...

  5. ZJOI Round2游记

    虽然一试很惨但是二试还是要来玩一下的 Day 0 到余姚了,然后到余姚边上的宾馆住来下来 顺便一问老师们对边上是不是有什么误解-- 吃完晚饭就回宾馆颓了 话说半夜真刺激--住隔壁那一位手突然骨折了,本 ...

  6. 17_python_成员

    一.类成员 1.字段 class Province: country = '中国' # 实例 (静态) 字段:类变量. 不属于对象, 对象可以访问 def __init__(self, name): ...

  7. ssh登录时在参数中加入密码的解决方案

    在使用ssh登录远程服务器的时候,在执行完ssh user@ip后,要输入登录密码,有时候登录密码记不住,这样以来Ian带来的很多的麻烦,有没有一种在ssh的参数中直接加入密码的方法呢?查看ssh的帮 ...

  8. Sentry有什么作用

    Sentry是一个异常日志集中收集系统,它可以捕捉到 stack trace, stack locals, preceding events和引发该异常的commit号.而当bug fix后,sent ...

  9. 【原创】手动导入SQLServer数据到SQLCE方法

    我找到一个工具,可以很容易把SQLServer里的数据导入到SQLCE: 工具名:Export2SqlCe.exe, 下载路径: http://exportsqlce.codeplex.com/rel ...

  10. Android系统架构及启动流程