Spring源码剖析之AbstractApplicationContext抽象类的refresh()方法

2023-05-16

Spring源码剖析之AbstractApplicationContext抽象类的refresh()方法 - 简书

Spring中AbstractApplicationContext抽象类的refresh()方法是用来刷新Spring的应用上下文的。下面Spring的应用上下文我都叫作context

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 刷新前的预处理.
            prepareRefresh();

            // 获取beanfactory 默认实现是:DefaultListableBeanFactory
            // 加载BeanDefition 并注册到BeanDefitionRegistry.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // BeanFactory的预准备?作(BeanFactory进??些设置,?如context的类加
            //载器等)(准备在此上下文中使用的bean工厂).
            prepareBeanFactory(beanFactory);

            try {
                // BeanFactory准备工作完成后进行的后置处理工作
                postProcessBeanFactory(beanFactory);

                // 实例化并调用实现了BeanFactoryPostProcessor接口的bean。
                invokeBeanFactoryPostProcessors(beanFactory);

                // 注册BeanPostProcessor(bean的后置处理器)在创建bean的前后执行.
                registerBeanPostProcessors(beanFactory);

                // 初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
                initMessageSource();

                // 初始化事件派发器。
                initApplicationEventMulticaster();

                // ?类重写这个?法,在容器刷新的时候可以?定义逻辑
                onRefresh();

                // 注册应?的监听器。就是注册实现了ApplicationListener接?的监听器
                //bean
                registerListeners();

                //
                //第??步:
                //初始化所有剩下的?懒加载的单例bean
                //初始化创建?懒加载?式的单例Bean实例(未设置属性)
                //填充属性
                //初始化?法调?(?如调?afterPropertiesSet?法、init-method?法)
                //调?BeanPostProcessor(后置处理器)对实例bean进?后置处
                 //
                finishBeanFactoryInitialization(beanFactory);

                // 最后一步:完成context的刷新。主要是调?LifecycleProcessor的onRefresh()?法,并且发布事件 (ContextRefreshedEvent).
                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();
            }
        }
    }

这个方法的每一行代码都很重要。已经在代码中标上序号,以下为各个部分的详细说明。

一.prepareRefresh();

①、这个方法设置context的启动日期。

②、设置context当前的状态,是活动状态还是关闭状态。

③、初始化context environment(上下文环境)中的占位符属性来源。

④、验证所有必需的属性。
源码:

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

        // 验证标记为所需的所有属性是否可解析:
        // 参阅 ConfigurablePropertyResolver#setRequiredProperties
        getEnvironment().validateRequiredProperties();

        // 存储预刷新 ApplicationListeners...
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            // 将本地应用程序侦听器重置为刷新前状态
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        // 允许提前收集应用程序的事件,
        // to be published once the multicaster is available...
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

二.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

让这个类(AbstractApplicationContext)的子类刷新内部bean工厂。实际上就是重新创建一个bean工厂。
obtainFreshBeanFactory()方法的代码如下:

/**
     * 告诉子类刷新内部bean工厂
     * @return the fresh BeanFactory instance
     * @see #refreshBeanFactory()
     * @see #getBeanFactory()
     */
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();//真正的刷新bean工厂。
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

上述代码中的refreshBeanFactory()最重要,其具体代码如下:

    /**
     * 此实现执行此上下文底层的实际刷新
      *bean factory,关闭以前的bean factory(如果有的话)和
      *为上下文生命周期的下一个阶段初始化一个新的bean工厂
     */
    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {//如果已经存在一个bean工厂那么就将其销毁,关闭。
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();//新建一个Bean工厂。
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);//自定义bean工厂。
            最经典的地方开始了 读取并加载xml文件 封装到beanDefinitions 接下来BeanDefinitions会贯穿整个Spring加载流程
            loadBeanDefinitions(beanFactory);//加载BeanDefinition
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;//将创建好的bean工厂的引用交给的context来管理。
            }
        }
        catch (IOException ex) {//加载bean定义资源的时候可能会抛出异常。
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

三、prepareBeanFactory(beanFactory);

上一步已经把工厂建好了,但是还不能投入使用,因为工厂里什么都没有,需要配置这个工厂的标准环境,比如context的类加载器和后处理器。看看这个方法的注释

   //准备BeanFactory以供在此上下文中使用  prepareBeanFactory(beanFactory);

四、postProcessBeanFactory(beanFactory);

上面对bean工厂进行了许多配置,现在需要对bean工厂进行一些处理。

①、添加一个ServletContextAwareProcessor到bean工厂中。

②、在bean工厂自动装配的时候忽略一些接口。如:ServletContextAware、ServletConfigAware

③、注册WEB应用特定的域(scope)到bean工厂中,以便WebApplicationContext可以使用它们。比如"request", "session", "globalSession", "application",

④、注册WEB应用特定的Environment bean到bean工厂中,以便WebApplicationContext可以使用它们。如:"contextParameters", "contextAttributes"
以下为这个方法的代码

/**
     * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
     */
    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }

五、invokeBeanFactoryPostProcessors(beanFactory)

这一步也是对bean工厂进行一些处理。这一步主要是调用所有的bean工厂处理器(BeanFactoryPostProcessor)对bean工厂进行一些处理。这个方法必须在所有的singleton初始化之前调用。

/**
     * 实例化并调用所有注册的 BeanFactoryPostProcessor beans,
     * respecting explicit order if given.
     * <p>必须在单例实例化之前调用
     */
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        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()));
        }
    }

六、registerBeanPostProcessors(beanFactory);

注册用来拦截bean创建的BeanPostProcessor bean.这个方法需要在所有的application bean初始化之前调用。把这个注册的任务委托给了PostProcessorRegistrationDelegate来完成。

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        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 (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, register the BeanPostProcessors that implement PriorityOrdered.首先,注册实现了PriorityOrdered接口的BeanPostProcessor
        sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // Next, register the BeanPostProcessors that implement Ordered.然后注册实现了Ordered接口的BeanPostProcessor
        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);
            }
        }
        sortPostProcessors(beanFactory, orderedPostProcessors);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // Now, register all regular BeanPostProcessors.注册所有常规的的BeanPostProcessor
        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.最后重新注册所有的内部BeanPostProcessor
        sortPostProcessors(beanFactory, internalPostProcessors);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // Re-register post-processor for detecting inner beans as ApplicationListeners,重新注册用来自动探测内部ApplicationListener的post-processor,这样可以将他们移到处理器链条的末尾。
        // moving it to the end of the processor chain (for picking up proxies etc).
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

七、initMessageSource();

初始化MessageSource接口的一个实现类。这个接口提供了消息处理功能。主要用于国际化/i18n。

八、initApplicationEventMulticaster();

为这个context初始化一个事件广播器(ApplicationEventMulticaster)。

AbstractApplicationContext中有一个常量:

/**
     * 工厂中ApplicationEventMulticaster bean的名称。.
     *如果未提供,则使用默认的 SimpleApplicationEventMulticaster is used.
     * @see org.springframework.context.event.ApplicationEventMulticaster
     * @see org.springframework.context.event.SimpleApplicationEventMulticaster
     */
    public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

这个常量就是的ApplicationEventMulticaster bean的名字。程序首先会检查bean工厂中是否有bean的名字和这个常量相同的,如果没有则说明没有那么就使用默认的ApplicationEventMulticaster 的实现:SimpleApplicationEventMulticaster

/**
     * 初始化 ApplicationEventMulticaster.
     * 如果上下文中没有定义,则使用SimpleApplicationEventMulticaster.
     * @see org.springframework.context.event.SimpleApplicationEventMulticaster
     */
    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {检查是否给context配了一个ApplicationEventMulticaster实现类
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {//如果没有,就是用默认的实现类 SimpleApplicationEventMulticaster
            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 + "]");
            }
        }
    }

九、onRefresh();

在AbstractApplicationContext的子类中初始化其他特殊的bean。其实就是初始化ThemeSource接口的实例。这个方法需要在所有单例bean初始化之前调用。

十、registerListeners();

注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的。这不会影响到其它监听器bean。在注册完以后,还会将其前期的事件发布给相匹配的监听器。

/**
     * 添加实现ApplicationListener作为侦听器的bean
     * 不影响其他侦听器,这些侦听器可以在不作为bean的情况下添加.
     */
    protected void registerListeners() {
        // 首先注册静态指定的侦听器.
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // 不要在这里初始化factorybean:我们需要保留所有常规bean
        // 未初始化以允许后处理程序应用于它们
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // 发布早期的应用程序事件 that we finally have a multicaster...至此,已经完成将监听器注册到ApplicationEventMulticaster中,下面将发布前期的事件给监听器。
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

十一、finishBeanFactoryInitialization(beanFactory);

完成bean工厂的初始化工作。这一步非常复杂,也非常重要,涉及到了bean的创建。第二步中只是完成了BeanDefinition的定义、解析、处理、注册。但是还没有初始化bean实例。这一步将初始化所有非懒加载的单例bean。
代码如下:

/**
     * 完成这个上下文的bean工厂的初始化
     * 初始化所有剩余的单例bean.
     */
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        //初始化此上下文的转换服务
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        //如果没有bean后处理程序,则注册一个默认的嵌入式值解析器
        // (例如PropertyPlaceholderConfigurer bean)以前注册的:
        // 此时,主要用于注释属性值的分辨率.
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        // 尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // 禁止使用临时类加载器进行类型匹配
        beanFactory.setTempClassLoader(null);

        // 允许缓存所有的bean的定义数据
        beanFactory.freezeConfiguration();

        // 实例化所有剩余的(非延迟初始化)单例(准备实例化bean)
        beanFactory.preInstantiateSingletons();
    }

我们着重看他是如何创建实例化bean的,跟进beanFactory.preInstantiateSingletons();,调用beanFactory的方法准备实例化bean, 这个beanFactory就是Spring默认是bean工厂, DefaultListableBeanFactory, 源码如下:方法不算很长,逻辑也很清楚, 一开始Spring取出当前上下文中所有的BeanName列表,因为在执行到这里之前,已经完成包扫描了所以说这个盛放beanName的list里面存放的就是所有的需要实例化的对象的全集,包含Spring自己的,和程序员自己添加的还包含Aspectj的

所以说,当前方法的目标很明了,就是遍历这个list中的每一个beanName,然后实例化当前beanName相应的bean

当然,如果想实例化,前提是不能是抽象类,不能是接口,非懒加载, 而且针对FactoryBean还有不同的处理模式

public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
    logger.debug("Pre-instantiating singletons in " + this);
}
//所有bean的名字
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
//todo 遍历一个副本以允许init方法,而init方法反过来注册新的bean定义。
// todo 盛放所有的beanName,所有的需要实例化的beanName都在这里,包括Spring断断续续添加的, Aspectj的, 程序员通过注解标识的
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
// todo 触发所有非延迟加载单例beans的初始化,主要步骤为调用getBean
for (String beanName : beanNames) {

    // todo 合并父类BeanDefinition,可以进入查看
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

    //todo 三个条件,抽象,单例,非懒加载
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

        if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            // todo 如果是FactoryBean则加上&
            // todo 检验是否是 FactoryBean 类型的对象
            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);
                }
            }
        }
        else {
            // todo 因为我们没有添加FactoryBean类型的对象, 一般都会进入这个getBean
            getBean(beanName);
        }
    }
}

下面接着跟进getBean(beanName);方法,顾名思义获取Bean,再往下跟下去,就算是本文的正文开始部分了,但是我想在这里提醒自己,一个比较有分量的剧透吧,当前的getBean(beanName)它是有返回值的,一会当我们往下跟进的是时候会发现会存在递归的现象,这一点巧妙的实现了@Autowired处理setter方式实现循环引用

ok,现在继续看代码,经过了几个空方法的传递,我们来到下面的代码中,它主要做了如下几件事

首先将传递进来的name转换成了beanName

原因1: FactoryBean的实现类的存储方式和其他的类完全相同,添加上&是获取不到的, 因此我们将&去掉 原因2: 解决别名的问题

为什么在创建bean之前先调用getSingleton()?

回想一下,现在是Spring启动的过程中,是在准备实例化bean,为什么一开始就来getSingleton(),跟进源码查看这个方法,它最终实现中有一行代码是这样的Object singletonObject = this.singletonObjects.get(beanName);而这个singletonObjects就是微观层面的IOC容器,循环创建刚开始时,IOC确实是空的,但是我前面存在剧透,一开始的getBean()方法是存在递归调用现象的,直接举2个例子: 第一:假如现在在实例化A,结果有发现需要给A注入B, 那Spring是不是得获得B,怎么获得呢? 递归使用getBean(BName)完成, 第二个例子: A被添加上了@Lazy注解,是懒加载的,但是终究有一个会通过getBean(AName)获取A,这是发现A是实例化需要B,B肯定已经实例化完事了,同样是通过递归getBean(BName)实现注入, 在这两个过程中就是getSingleton()保证不会重复创建已经存在的实例

我们关注的重点其实是第二个getSingleton(beanName()->{xxx})

在第二个getSingleton()方法中才是真正的去实例化bean的方法

最后,在当前的方法最后将bean返回了

前面我就是说过了,getBean(beanName)存在递归调用的情况,为什么我会一直说这个事呢,因为如果不知道这个事的话,这些代码看起来是没有头绪的,但是明白这个事,看代码就变得很有逻辑,我在简单总结一下怎个玩这个递归呢? 假设现在通过getBean(AName)来注入A对象,但是呢发现了A依赖B对象,于是在getBean(AName)里面调用getBean(BName),通过这个方法返回出B对象完成A的注入

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

// 将传递进来的name
final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
// 及早的检查一下有没有已经注册了的单例对象
Object sharedInstance = getSingleton(beanName);// todo ::: name=myService时,这次来调用的就是 DefaultSingletonBeanRegistry中的 getSingleton() , 不同之处是多传递了一个true
if (sharedInstance != null && args == null) {
    // 如果存在的话,将其取出赋值给bean,后续直接返回这个bean
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
    // Fail if we're already creating this bean instance:
    // We're assumably within a circular reference.
    // 来到这里就说明要获取的bean还没有实例化过
    // 于是检验一下,如果是原形,直接抛异常
    if (isPrototypeCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }

    // Check if bean definition exists in this factory.
    // 检查是否存在默认的父工厂
    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // Not found -> check parent.
        String nameToLookup = originalBeanName(name);
        if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                    nameToLookup, requiredType, args, typeCheckOnly);
        }
        else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
        }
        else {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
    }

    if (!typeCheckOnly) {
        // 将当前的beanName存放到AlreadeyCreated这个set集中,标识这个bean被创建了
        markBeanAsCreated(beanName);
    }

    try {
        final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        checkMergedBeanDefinition(mbd, beanName, args);

        // Guarantee initialization of beans that the current bean depends on.
        // 确保当前bean所依赖的bean都已经初始化好了
        String[] dependsOn = mbd.getDependsOn();
        if (dependsOn != null) {
            for (String dep : dependsOn) {
                if (isDependent(beanName, dep)) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                }
                registerDependentBean(dep, beanName);
                try {
                    getBean(dep);
                }
                catch (NoSuchBeanDefinitionException ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                }
            }
        }

        // Create bean instance.
        if (mbd.isSingleton()) {
          // 实例化bean
            sharedInstance = getSingleton(beanName, () -> { 
                    // 真正的完成bean的创建
                    return createBean(beanName, mbd, args);
            
            });

            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
        // 下面是进行其他的检查工作,这里不再深究了
        else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
                beforePrototypeCreation(beanName);
                prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
                afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
        }

        else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
                throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
                Object scopedInstance = scope.get(beanName, () -> {
                    beforePrototypeCreation(beanName);
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                });
                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
                throw new BeanCreationException(beanName,
                        "Scope '" + scopeName + "' is not active for the current thread; consider " +
                        "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                        ex);
            }
        }
    }
    catch (BeansException ex) {
        cleanupAfterBeanCreationFailure(beanName);
        throw ex;
    }
}

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
    try {
        T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
        if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
        return convertedBean;
    }
    catch (TypeMismatchException ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Failed to convert bean '" + name + "' to required type '" +
                    ClassUtils.getQualifiedName(requiredType) + "'", ex);
        }
        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    }
}
return (T) bean;
}

经过了上面一顿扯,然后我们继续往下跟,看看createBean(beanName, mbd, args)方法中是如何实例化我们的Bean的, 上面的方法是在AbstractBeanFactory中,createBean(beanName, mbd, args)是它的抽象方法, 那实现类是哪个呢?

AbstractAutowireCapableBeanFactory,隆重的夸一下这个类,Spring都称赞这个类是有有才华的

深入细节查看:CSDN

十二、finishRefresh();

完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)。

/**
     * 完成此上下文的刷新,调用LifecycleProcessor的
     * onRefresh() method and publishing the
     * {@link org.springframework.context.event.ContextRefreshedEvent}.
     */
    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);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring源码剖析之AbstractApplicationContext抽象类的refresh()方法 的相关文章

随机推荐

  • 启动AndroidStudio报错Missing essential plugin:org.jetbrains.android Please reinstall Android Studio...

    问题 今天升级Android Studio 后 xff0c 打算重新启动 xff0c 却发现启动报错如下 xff1a Missing essential plugin span class token punctuation span or
  • 如何在Oracle官网下载JAVA SE 8版本(JDK 1.8.0)

    目录 一 判断你的情况是否符合本文二 JDK的安装三 配置环境变量环境变量设置测试阶段 一 判断你的情况是否符合本文 当你搜索http www oracle com technetwork java javase downloads ind
  • kendoGrid合并单元格

    kendoGrid默认API中并没有合并单元格的方法 xff0c 故自己借鉴网友的代码并做了改造 xff0c 下述代码及完成了kendoGrid中的行的合并 xff08 在 dataBound事件中完成 xff09 span class t
  • Git合并指定文件到其他分支

    1 合并某个分支上的指定commit span class token comment 在dev分支合并bugfix分支上的 ac0ca63 commit span git branch span class token operator
  • shell命令—find

    find命令 span class token comment 删除 home fengshuiyue目录下一周前的目录 span fengshuiyue 64 ralc span class token operator gt span
  • shell命令—date

    date命令 span class token comment 获取当前时间 日期格式是 YYYY mm dd HH MM SS span span class token function date span span class tok
  • 大华硬盘录像机、网络摄像机、 网络硬盘录像机外网远程设置DDNS方法

    1 为了便于解释在下文介绍中 xff0c 硬盘录像机 网络摄像机 网络硬盘录像机统一称为 大华设备 2 外网最好是电信 如果不是 xff0c 那必须要确认客户的外网 IP 是唯一的 xff0c 不是与其他用户共用的 3 首先确保 大华设备
  • LibCurl HTTP部分详细介绍

    目录索引 xff1a 一 LibCurl基本编程框架 二 一些基本的函数 三 curl easy setopt函数部分选项介绍 四 curl easy perform 函数说明 xff08 error 状态码 xff09 五 libcurl
  • navicat连接oracle报错:ORA-12737 Instant Client Light:unsupported server character set ZHS16GBK

    今天使用Navicat连接Oracle数据库 xff0c 报了下面的这个错误 xff1a ORA 12737 Instant Client Light unsupported server character set ZHS16GBK 从这
  • RabbitMQ 与 Kafka深度解析(二)

    介绍 作为一名处理大量基于微服务的系统的软件架构师 xff0c 我经常会遇到一个反复出现的问题 xff1a 我应该使用RabbitMQ还是Kafka xff1f 出于某种原因 xff0c 许多开发人员认为这些技术是可以互换的 虽然在某些情况
  • VMWare报错"指定的文件不是虚拟磁盘"或“The file specified is not a virtual disk”

    今天打开原来创建的虚拟机 xff0c 突然报错 指定的文件不是虚拟磁盘 xff0c 如下图 xff1a 由于之前这个虚拟机创建了快照 xff0c 因此下面的解决方法是基于快照的 1 打开虚拟机的 vmx文件 xff0c 我的虚拟机名字为 U
  • Javascript模块加载框架——seajs

    最近看了一些开源web的项目 xff0c 发现其前台采用的框架seajs在编写JavaScript代码上很是方便 xff0c 现将学习的记录记于此 1 什么是JavaScript模块加载 为了解决不同javascript库里操作对象的命名冲
  • JS实现浏览器打印、打印预览

    目前正在做浏览器端采用JS方式实现打印这么一个功能 xff0c JS打印实现的方法很多 xff0c 但是兼容各个浏览器实现打印预览的功能有些棘手 xff0c 现将实现的内容及遇到的问题记录下来 xff0c 希望有大牛看到所提的问题后可以给予
  • 日期与天干地支算法

    天干地支五行对照表 天干 地支与五行的对应表 甲 乙 丙 丁 戊 己 庚 辛 壬 癸 阳 阴 阳 阴 阳 阴 阳 阴 阳 阴 木 木 火 火 土 土 金 金 水 水 子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥 鼠 牛 虎 兔 龙 蛇 马
  • TR技术评审节点

    产品开发中 xff0c TR是技术评审节点 下面是某产品的技术评审点 xff0c 供参考 xff1a TR1 概念阶段技术评审点 xff1a 产品需求和概念技术评审 xff08 业务需求评审 xff09 是ISO IEC TR 19768
  • linux虚拟机重新启动后不能联网的问题

    这里解决的是linux中 xff0c 曾经能连上网的情况下 xff0c 重启后或一段时间没上后 xff0c 不能联网的问题 xff08 安装后就没连上网 xff0c 就乖乖安装各种教程来一下啊 xff0c 这里可能不一定适合你 当然 xff
  • Spring MVC执行流程

    Spring MVC 框架是高度可配置的 xff0c 包含多种视图技术 xff0c 例如 JSP FreeMarker Tiles iText 和 POI Spring MVC 框架并不关心使用的视图技术 xff0c 也不会强迫开发者只使用
  • 数据分析必备——SQL入门基础知识

    数据说 梦想季 一直很喜欢一句话 xff1a 山鸟与鱼不同路 xff0c 从此山水不相逢 意思就是如果你现在不够优秀 xff0c 即使遇见了 xff0c 也不配拥有 努力是唯一的方向 xff01 导读 xff1a 科学技术的快速发展正在改变
  • CentOS6.5安装nginx

    转载 xff1a http blog csdn net yinwenjie article details 46620711 2 Nginx的安装 2 1 准备工作 操作系统 xff1a centOS 6 5 Nginx的下载地址 xff1
  • Spring源码剖析之AbstractApplicationContext抽象类的refresh()方法

    Spring源码剖析之AbstractApplicationContext抽象类的refresh 方法 简书 Spring中AbstractApplicationContext抽象类的refresh 方法是用来刷新Spring的应用上下文的