Spring容器创建时refresh()方法源码分析

入口:

import com.stu.config.RecyleLifeBean;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    @Test
    public void testComponnet1() {
        // 创建IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(RecyleLifeBean.class);
        System.out.println("IOC容器创建完毕");

         String str = applicationContext.getEnvironment().getProperty("key");

        // 关闭IOC容器
        applicationContext.close();
    }
}

AbstractApplicationContext抽象类种的refresh():

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

        }
    }

来深究下这个方法到底干了些什么。
首先发现这个加了synchronized锁,保证容器只有一个被创建。这是加的对象

private final Object startupShutdownMonitor;

这是在构造器中创建的对象:

    public AbstractApplicationContext() {
        this.logger = LogFactory.getLog(this.getClass());
        this.id = ObjectUtils.identityToString(this);
        this.displayName = ObjectUtils.identityToString(this);
        this.beanFactoryPostProcessors = new ArrayList();
        this.active = new AtomicBoolean();
        this.closed = new AtomicBoolean();
        this.startupShutdownMonitor = new Object();
        this.applicationListeners = new LinkedHashSet();
        this.resourcePatternResolver = this.getResourcePatternResolver();
    }

容器创建,到底都做了那些操作。
首先,this.prepareRefresh()方法;

1、状态设置。
2、有两个方法,加载了服务器的一些信息和判断必填项是否都完整。包括文件路径等

protected void prepareRefresh() {
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
        if (this.logger.isDebugEnabled()) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Refreshing " + this);
            } else {
                this.logger.debug("Refreshing " + this.getDisplayName());
            }
        }

		// 这两个方法加载了服务器的一些信息和判断必填项是否都完整
        this.initPropertySources();
        this.getEnvironment().validateRequiredProperties();
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet(this.applicationListeners);
        } else {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        this.earlyApplicationEvents = new LinkedHashSet();
    }

this.obtainFreshBeanFactory()方法:

返回一个bean工厂:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        this.refreshBeanFactory();
        return this.getBeanFactory();
    }

其中的refreshBeanFactory() 方法:
当前BeanFactory != null就清除当前BeanFactory中的所有单例bean,并将BeanFactory 置为null。再重新创建一个空的BeanFactory。

 protected final void refreshBeanFactory() throws BeansException {
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
            this.loadBeanDefinitions(beanFactory);
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }

接着是this.prepareBeanFactory(beanFactory):
显然是将上面返回的添加了注解的beanFactory,做一些准备工作。
比较复杂,它主要
1、设置类加载器、标准bean的EL解析、注册环境信息、和设置后置处理器ApplicationContextAwareProcessor(也包含前置,是BeanPostProcessor的实现类)
2、ignoreDependencyInterface是忽视掉Aware相关的依赖接口,比如EnvironmentAware、EmbeddedValueResolverAware、ApplicationContextAware等
3、registerResolvableDependency注册依赖,比如beanFactory、ResourceLoader资源类加载、ApplicationEventPublisher事件发布、ApplicationContext环境上下文设计。
4、添加addBeanPostProcessor和检查当前环境信息(包括getSystemProperties、getSystemEnvironment等)是否加载,没有加载则加载。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setBeanClassLoader(this.getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
        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);
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
        if (beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        if (!beanFactory.containsLocalBean("environment")) {
            beanFactory.registerSingleton("environment", this.getEnvironment());
        }

        if (!beanFactory.containsLocalBean("systemProperties")) {
            beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
        }

        if (!beanFactory.containsLocalBean("systemEnvironment")) {
            beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
        }

    }

this.postProcessBeanFactory(beanFactory)方法:
该方法是允许再容器初始化完成之前,自定义通过beanFactory对上下文进行操作。

 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

this.invokeBeanFactoryPostProcessors(beanFactory)方法:
实例化并调用所有已注册的BeanFactoryPostProcessor。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

    }

this.registerBeanPostProcessors(beanFactory)方法:
注册所有BeanPostProcessor

 protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 找到所有BeanPostProcessor的实现类,逐一注册
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }

this.initMessageSource()方法:
初始化MessageSource组件(做国际化功能;消息绑定,消息解析)。

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.isTraceEnabled()) {
                this.logger.trace("Using MessageSource [" + this.messageSource + "]");
            }
        } else {
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(this.getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton("messageSource", this.messageSource);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("No 'messageSource' bean, using [" + this.messageSource + "]");
            }
        }

    }

实际应用中的体现:(当然你也可以直接用JDK的java.util包中提供了几个支持本地化的格式化操作工具类:NumberFormat、DateFormat、MessageFormat)。
比如:


//①信息格式化串    
String pattern1 = "呵呵哒";  
String pattern2 = "么么哒";  
 
//②用于动态替换占位符的参数    
Object[] params = {"John", new GregorianCalendar().getTime(), 1.0E3};  
 
//③使用默认本地化对象格式化信息    
String msg1 = MessageFormat.format(pattern1, params);  
 
//④使用指定的本地化对象格式化信息    
MessageFormat mf = new MessageFormat(pattern2, Locale.US);  
String msg2 = mf.format(params);

但是通常我们选择下面的操作过程。

    @Autowired
    ApplicationContext applicationContext;

    //@Bean
    @Bean("getUserBean")
    public User getUser(){
        String str = applicationContext.getMessage("com.stu",new Object[]{"heheda"}, Locale.US)
        return new User();
    }

this.initApplicationEventMulticaster()方法:
初始化事件监听多路广播器(多播器)。beanFactory有多路广播器则获得,没有则注册applicationEventMulticaster。主要用于事件发布监听。

 protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
            this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        } else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("No 'applicationEventMulticaster' bean, using [" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
            }
        }

    }

this.onRefresh()方法:这是空壳子方法。估计是预留方法。
this.registerListeners()方法:
正如文字表现就是该方法作用就是注册监听器。这个是和事件发布相关。
1、先将的ApplicationListener放入this.getApplicationEventMulticaster().addApplicationListener(listener)中,再2、将实现了ApplicationListener.class放入this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
3、发布早期的监听器,this.getApplicationEventMulticaster().multicastEvent(earlyEvent);这个反射调用。

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

    }

this.finishBeanFactoryInitialization(beanFactory)方法:
实例化所有的bean。

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((strVal) -> {
                return 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();
    }

this.finishRefresh()方法:
初始化生命周期处理器LifecycleProcessor并调用其onrefresh方法,找到SmartLifecycle接口的所有实现类并调用start方法,发布事件告知listener,如果设置了JMX相关属性,还会调用LiveBeansView的registerApplicationContext方法。

protected void finishRefresh() {
        // 清空此资源加载器中所有的资源缓存
        this.clearResourceCaches();
        // 为此上下文初始化生命周期处理器
        this.initLifecycleProcessor();
        // 首先将刷新完毕事件传播到生命周期处理器
        this.getLifecycleProcessor().onRefresh();
        // 容器完成初始化后调用finishRefresh()时会发布ContextRefreshedEvent事件
        this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
        // 容器完成初始化后调用finishRefresh()时会发布ContextRefreshedEvent事件
        LiveBeansView.registerApplicationContext(this);
    }

清空此资源加载器中所有的资源缓存。
这个涉及到Spring核心之——资源加载器。
DefaultResourceLoader ,默认资源加载器,是 ResourceLoader 接口的默认实现类,用于加载资源配置。AbstractApplicationContext 直接继承此类。

package org.springframework.core.io;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
 * 通过ResourceEditor来使用,作为一个基础类来服务于
 * org.springframework.context.support.AbstractApplicationContext
 *
 * 如果location 的值是一个 URL,将返回一个UrlResource资源;
 * 如果location 的值非URL路径或是一个"classpath:"相对URL,则返回一个ClassPathResource.
 *
 * @author Juergen Hoeller
 * @since 10.03.2004
 * @see FileSystemResourceLoader
 * @see org.springframework.context.support.ClassPathXmlApplicationContext
 */
public class DefaultResourceLoader implements ResourceLoader {

    /**
     * 可为空的类加载器。
     * 默认情况下,类加载器将在这个ResourceLoader初始化时使用线程上下文类加载器进行访问。
     */
    @Nullable
    private ClassLoader classLoader;
    /** 路径协议解析的Set集合 */
    private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);

    /** 用于资源缓存的Map的映射集 */
    private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);


    /**
     * 无参构造方法创建一个新的DefaultResourceLoader对象,并设置类加载器.
     * @see java.lang.Thread#getContextClassLoader()
     */
    public DefaultResourceLoader() {
        /**
         * 底层实现是按以下递进获取,有则返回:
         * 当前线程的类加载、ClassUtils.class 的加载器、系统类加载
         */
        this.classLoader = ClassUtils.getDefaultClassLoader();
    }

    /**
     * 有参构造方法,主动注入一个类加载
     * @param classLoader 用来加载类路径资源的类加载器,因为这个类加载器可以null,所以可传null值
     */
    public DefaultResourceLoader(@Nullable ClassLoader classLoader) {
        this.classLoader = classLoader;
    }


    /**
     * setter 方法注入一个(可为null)的类加载器
     */
    public void setClassLoader(@Nullable ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    /**
     * 返回用于加载类资源的类加载器。
     * 如果未null,则通过ClassUtils.getDefaultClassLoader()重新获取。
     * @see ClassPathResource
     */
    @Override
    @Nullable
    public ClassLoader getClassLoader() {
        return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());
    }

    /**
     * 用这个资源加载器注册给定的解析器(前面的文章也讲说,解析器用于解析多个资源路径)。
     * 任何这样的解析器都会在这个加载程序的标准解析规则之前被调用。
     * 因此,它还可能覆盖任何默认规则。
     * @since 4.3
     * @see #getProtocolResolvers()
     */
    public void addProtocolResolver(ProtocolResolver resolver) {
        Assert.notNull(resolver, "ProtocolResolver must not be null");
        this.protocolResolvers.add(resolver);
    }

    /**
    * 返回当前注册的协议解析器集合,允许进行自行修改。
     * @since 4.3
     */
    public Collection<ProtocolResolver> getProtocolResolvers() {
        return this.protocolResolvers;
    }

    /**
     * 获取由 Resource 键入的给定值类型的缓存。
     * @param valueType 值类型, 比如一个 ASM MetadataReader
     * @return Map缓存, 在ResourceLoader级别进行分享
     * @since 5.0
     */
    @SuppressWarnings("unchecked")
    public <T> Map<Resource, T> getResourceCache(Class<T> valueType) {
        return (Map<Resource, T>) this.resourceCaches.computeIfAbsent(valueType, key -> new ConcurrentHashMap<>());
    }

    /**
     * 清空此资源加载器中所有的资源缓存
     * @since 5.0
     * @see #getResourceCache
     */
    public void clearResourceCaches() {
        this.resourceCaches.clear();
    }

    /**
     * 从指定的路径获取资源,不能为null
     *
     * 获取资源的优先策略从高到底依次是:
     * 1.从协议解析器集合遍历每个协议器尝试解析指定位置的资源;
     * 2.从"/"开头的绝对路径尝试解析资源;
     * 3.从"classpath:"的类相对路径解析资源;
     * 4.最后从网络URL处解析资源。
     */
    @Override
    public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
        // 遍历协议解析器的集合
        for (ProtocolResolver protocolResolver : this.protocolResolvers) {
            // 然后用当前的协议解析来解析指定路径的资源
            Resource resource = protocolResolver.resolve(location, this);
            if (resource != null) {
                // 如果在当前协议解析器下解析的资源不为空,则返回该资源
                return resource;
            }
        }
        // 程序运行到这里,要么说明协议解析器集合为空,
        // 要么说明协议解析器集合中的所有协议解析器解析指定位置的资源都为null
        // 那么就对资源路径判断
        if (location.startsWith("/")) {
            // 此方法是本类中的方法,下面分析
            return getResourceByPath(location);
        }
        // 如果资源路径不以 "/" 为开始的绝对路径标识,
        // 则判断是否以默认方式 "classpath:" 开头
        else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
            // 如果以默认的"classpath:"开头,则说明资源是类路径的相对资源
            return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
        }
        // 在不然,就尝试从远处网络URL资源加载
        else {
            try {
                // 尝试将路径位置解析为URL…
                URL url = new URL(location);
                return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
            }
            catch (MalformedURLException ex) {
                // 没有URL可以解析为资源路径
                return getResourceByPath(location);
            }
        }
    }

    /**
     * 返回给定路径上的资源地址引用。
     * 默认实现支持类路径位置。 这应该适用于独立实现,但可以被重写,
     * 比如:用于针对Servlet容器的实现。
     * @param path 资源的路径
     * @return 对应的资源引用
     * @see ClassPathResource
     * @see org.springframework.context.support.FileSystemXmlApplicationContext#getResourceByPath
     * @see org.springframework.web.context.support.XmlWebApplicationContext#getResourceByPath
     */
    protected Resource getResourceByPath(String path) {
        return new ClassPathContextResource(path, getClassLoader());
    }


    /**
     * 类路径库,通过实现上下文源接口显式地表示上下文相关路径。
     */
    protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {

        public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) {
            super(path, classLoader);
        }

        @Override
        public String getPathWithinContext() {
            return getPath();
        }

        @Override
        public Resource createRelative(String relativePath) {
            String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
            return new ClassPathContextResource(pathToUse, getClassLoader());
        }
    }
}

初始化异常,则调用如下两个方法,销毁beans、取消刚开始设置的刷新状态
this.destroyBeans() 和this.cancelRefresh(var9);

销毁beans:

 protected void destroyBeans() {
        this.getBeanFactory().destroySingletons();
    }

取消刚开始设置的刷新状态:

 protected void cancelRefresh(BeansException ex) {
        this.active.set(false);
    }

最后执行 this.resetCommonCaches()方法:

    protected void resetCommonCaches() {
        // 清空反射集合
        ReflectionUtils.clearCache();
        // 清空注解集合
        AnnotationUtils.clearCache();
        // ResolvableType更好的处理泛型,清除泛型集合
        ResolvableType.clearCache();
        // 清除当前类加载器
        CachedIntrospectionResults.clearClassLoader(this.getClassLoader());
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值