spring boot refresh流程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yj1499945/article/details/87090676

这里使用的是spring boot 1.5.9

先看一下具体的实现方法

    public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

看上去好像很少其实整个spring boot启动的大部分时间都在这里了

prepareRefresh

设置了启动时间,初始化了一些配置,校验一些必须的配置是否存在

prepareBeanFactory

对bean工厂设置了很多的属性,比如:classloader(Appclassloader), 设置表达式解析器(解析bean定义中的一些表达式 StandardBeanExpressionResolver),添加属性编辑注册器(ResourceEditorRegistrar),添加BeanPostProcessor

注入一些其它信息的bean,比如environment、systemProperties等。

postProcessBeanFactory

让子类上下文做一些事情,在spring boot中使用的是AnnotationConfigEmbeddedWebApplicationContext

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        super.postProcessBeanFactory(beanFactory);
        if (this.basePackages != null && this.basePackages.length > 0) {
            this.scanner.scan(this.basePackages);
        }

        if (this.annotatedClasses != null && this.annotatedClasses.length > 0) {
            this.reader.register(this.annotatedClasses);
        }

    }

子类做的事情就是去设置的包路径下扫描和注册bean。但是这个值需要你进行设置默认为Null

invokeBeanFactoryPostProcessors

字面上的意思就是初始化BeanFactoryPostProcessors。比如:ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor等。

    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList();
            Iterator var6 = beanFactoryPostProcessors.iterator();

            while(var6.hasNext()) {
                BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }
}
}

上面的代码是截取的一部分,可以看出来先处理了传入的一些beanFactoryPostProcessors。调用核心方法postProcessBeanDefinitionRegistry,这个方法就是不同的实现类都是不一样的。这里说一下ConfigurationClassPostProcessor这个类的实现。这个类的postProcessBeanDefinitionRegistry方法会去寻找所有带着@Configuration的class。会对类进行解析和保存到beanfactory这里只保存了一个字符串,其他操作都没有做。这下来是如何操作的这里就不说了,展开实在太多。

接下来根据三个优先级分别从beanfactoty中获取实现BeanDefinitionRegistryPostProcessor的类,并且调用postProcessBeanDefinitionRegistry方法。优先级分别为PriorityOrdered,Ordered,都不实现的。

扫描二维码关注公众号,回复: 6630427 查看本文章

接下来就是上面的套路去获取实现BeanFactoryPostProcessor的类,并且调用postProcessBeanFactory方法。

这里多说一句,BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的区别。

BeanFactoryPostProcessor

从名字上看, 它是BeanFactory的后处理类, 我们先了解下BeanFactory.

BeanFactory的地位相当高, 它是各种Bean的工厂, 提供了一系列的getBean方法. 常用的ApplicationContext就继承了它.

BeanFactoryPostProcessor就是BeanFactory的后处理类, 我们可以在BeanFactory初始化之后做一些操作. 它提供了个postProcessBeanFactory()方法, 这个方法被调用的时候, 所有的Bean已经被创建, 但是还没有被初始化. 也就是说, 通过它我们可以在初始化任何Bean之前, 做各种操作, 甚至读取并修改BeanDefinition(bean定义的元数据).

BeanDefinitionRegistryPostProcessor

这个接口继承了BeanFactoryPostProcessor. 从名字上来看, 这个接口是BeanDefinitionRegistry的后处理器, 我们先介绍下BeanDefinitionRegistry.

BeanDefinitionRegistry是用来注册BeanDefinition的. BeanDefinition就是Bean的配置元数据或Bean的描述信息, 比如Bean的属性值, 构造方法的参数值等. 上面的BeanFactoryBeanDefinition也是由它注册的.

BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的扩展, 允许在BeanFactoryPostProcessor被调用之前对BeanDefinition做一些操作, 尤其是它可以注册BeanFactoryPostProcessorBeanDefinition. 它提供了一个方法postProcessBeanDefinitionRegistry(), 这个方法被调用的时候, 所有的BeanDefinition已经被加载了, 但是所有的Bean还没被创建.

注意:

  • 所有的Bean生成都有个顺序: 定义 --> 创建 --> 初始化.
  • BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry方法在Bean定义但还没被创建的时候执行.
  • BeanFactoryPostProcessorpostProcessBeanFactory方法在Bean创建但还没被初始化的时候执行

 

registerBeanPostProcessors

接下来就是注册BeanPostProcessors.首先也是根据顺序从beanfactory中拿到对应实现BeanPostProcessor的类。

根据优先级分别为PriorityOrdered,Ordered,都不实现的。将三种类别的BeanPostProcessors添加到beanfactory中,这个添加是根据优先级添加的。

initMessageSource

    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (beanFactory.containsLocalBean("messageSource")) {
            this.messageSource = (MessageSource)beanFactory.getBean("messageSource", MessageSource.class);
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource)this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    hms.setParentMessageSource(this.getInternalParentMessageSource());
                }
            }

            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        } else {
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(this.getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton("messageSource", this.messageSource);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Unable to locate MessageSource with name 'messageSource': using default [" + this.messageSource + "]");
            }
        }

    }

初始化了一个DelegatingMessageSource类作为国际化的处理类。

initApplicationEventMulticaster

首先我们要分清楚一些概念

事件:ApplicationEvent

事件监听器:ApplicationListener,对监听到的事件进行处理。

事件广播器:ApplicationEventMulticaster,将Springpublish的事件广播给所有的监听器。

    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
            this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        } else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [" + this.applicationEventMulticaster + "]");
            }
        }

    }

这个方法初始化了一个SimpleApplicationEventMulticaster作为默认的广播器

onRefresh

这个方法由AnnotationConfigEmbeddedWebApplicationContext的父类EmbeddedWebApplicationContext实现

    private void createEmbeddedServletContainer() {
        EmbeddedServletContainer localContainer = this.embeddedServletContainer;
        ServletContext localServletContext = this.getServletContext();
        if (localContainer == null && localServletContext == null) {
            EmbeddedServletContainerFactory containerFactory = this.getEmbeddedServletContainerFactory();
            this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(new ServletContextInitializer[]{this.getSelfInitializer()});
        } else if (localServletContext != null) {
            try {
                this.getSelfInitializer().onStartup(localServletContext);
            } catch (ServletException var4) {
                throw new ApplicationContextException("Cannot initialize servlet context", var4);
            }
        }

        this.initPropertySources();
    }

这是其中一部分代码,这里主要生成了一个TomcatEmbeddedServletContainer的容器。这里一共有三种容器

UndertowEmbeddedServletContainer

JettyEmbeddedServletContainer

TomcatEmbeddedServletContainer

registerListeners

 protected void registerListeners() {
        Iterator var1 = this.getApplicationListeners().iterator();

        while(var1.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var1.next();
            this.getApplicationEventMulticaster().addApplicationListener(listener);
        }

        String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
        String[] var7 = listenerBeanNames;
        int var3 = listenerBeanNames.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String listenerBeanName = var7[var4];
            this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            Iterator var9 = earlyEventsToProcess.iterator();

            while(var9.hasNext()) {
                ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
                this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }

    }

把Spring容器内的时间监听器和BeanFactory中的时间监听器都添加的事件广播器中

finishBeanFactoryInitialization

 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
                public String resolveStringValue(String strVal) {
                    return AbstractApplicationContext.this.getEnvironment().resolvePlaceholders(strVal);
                }
            });
        }

        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader((ClassLoader)null);
        beanFactory.freezeConfiguration();
        beanFactory.preInstantiateSingletons();
    }

还记得之前beanfactory中那些只有字符串对象的bean吗,在这里他们要通过反射获取真正的对象了。最重要通过preInstantiateSingletons方法,这个beanfactory是默认的DefaultListableBeanFactory

finishRefresh

    protected void finishRefresh() {
        this.initLifecycleProcessor();
        this.getLifecycleProcessor().onRefresh();
        this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
        LiveBeansView.registerApplicationContext(this);
    }

这里对实现了LifecycleProcessoer的类进行refresh。

发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作

还有就是通过registerApplicationContext注册jmx相关的东西

猜你喜欢

转载自blog.csdn.net/yj1499945/article/details/87090676