spring 实例化配置文件源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取 2000+ 道 Java 面试题

引入

spring配置文件是怎么实例化的呢?

直接调试来看看。

    package test;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class TestNull {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            System.out.println(context.getBean("redisTemplate").toString()+"%%%%%%%");
        }
    }

20191102100482\_1.png
先全局看看,这个加载的过程。
20191102100482\_2.png
可以看到configLocations属性是存放spring配置文件路径的。下面的refresh()方法应该是核心。

核心-refresh()

    public void refresh() throws BeansException, IllegalStateException {
            Object var1 = this.startupShutdownMonitor;
            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 var5) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
                    this.destroyBeans();
                    this.cancelRefresh(var5);
                    throw var5;
                }

            }
        }

可以看到refresh加了同步锁,startupShutdownMonitor:refresh方法和destory方法公用的一个监视器,避免两个方法同时执行。

接下来看到prepareRefresh()方法:

refresh()的prepareRefresh()

     protected void prepareRefresh() {
            this.startupDate = System.currentTimeMillis();
            this.closed.set(false);
            this.active.set(true);
            if(this.logger.isInfoEnabled()) {
                this.logger.info("Refreshing " + this);
            }

            this.initPropertySources();
            this.getEnvironment().validateRequiredProperties();
        }

     protected void initPropertySources() {
        }

刷新的时候不允许关闭,是需要活跃的,打印正在刷新的对象,

验证所需属性。

    public void validateRequiredProperties() {
            MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
            Iterator var2 = this.requiredProperties.iterator();

            while(var2.hasNext()) {
                String key = (String)var2.next();
                if(this.getProperty(key) == null) {
                    ex.addMissingRequiredProperty(key);
                }
            }

            if(!ex.getMissingRequiredProperties().isEmpty()) {
                throw ex;
            }
        }

主要是验证requiredProperties属性value是非空的,是空的话就抛出异常。

refresh()的obtainFreshBeanFactory()

        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            this.refreshBeanFactory();
            ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
            }

            return beanFactory;
        }

会看到这里不是简单的new一个ConfigurableListableBeanFactory代码。在new之前会进行刷新下BeanFactory,下面来看看

obtainFreshBeanFactory()的refreshBeanFactory()

    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);
                Object var2 = this.beanFactoryMonitor;
                synchronized(this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }
            } catch (IOException var5) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
            }
        }

可以看到先判断是否有beanFactory对象,有的话就销毁bean和关闭beanFactory,下面会创造新的,然后加载bean定义,后面在赋值给this.beanFactory的时候用来beanFactoryMonitor来控制同步,可能有其他地方也会赋值。

refresh()的prepareBeanFactory()

    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(ResourceLoaderAware.class);
            beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
            beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
            beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
            beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
            beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
            beanFactory.registerResolvableDependency(ResourceLoader.class, this);
            beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
            beanFactory.registerResolvableDependency(ApplicationContext.class, 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());
            }

        }

配置工厂的标准上下文特性,例如上下文的类加载器和后处理器。

refresh()的finishRefresh()

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

初始化生命周期处理器(没有的话就使用默认的),调用LifecycleProcessor的onRefresh()方法,发布上下文刷新事件t,注册applicationContext。

finishRefresh()的onRefresh()

        public void onRefresh() {
            this.startBeans(true);
            this.running = true;
        }
    private void startBeans(boolean autoStartupOnly) {
            Map<String, Lifecycle> lifecycleBeans = this.getLifecycleBeans();
            Map<Integer, DefaultLifecycleProcessor.LifecycleGroup> phases = new HashMap();
            Iterator var4 = lifecycleBeans.entrySet().iterator();

            while(true) {
                Entry entry;
                Lifecycle bean;
                do {
                    if(!var4.hasNext()) {
                        if(phases.size() > 0) {
                            List<Integer> keys = new ArrayList(phases.keySet());
                            Collections.sort(keys);
                            Iterator var10 = keys.iterator();

                            while(var10.hasNext()) {
                                Integer key = (Integer)var10.next();
                                ((DefaultLifecycleProcessor.LifecycleGroup)phases.get(key)).start();
                            }
                        }

                        return;
                    }

                    entry = (Entry)var4.next();
                    bean = (Lifecycle)entry.getValue();
                } while(autoStartupOnly && (!(bean instanceof SmartLifecycle) || !((SmartLifecycle)bean).isAutoStartup()));

                int phase = this.getPhase(bean);
                DefaultLifecycleProcessor.LifecycleGroup group = (DefaultLifecycleProcessor.LifecycleGroup)phases.get(Integer.valueOf(phase));
                if(group == null) {
                    group = new DefaultLifecycleProcessor.LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                    phases.put(Integer.valueOf(phase), group);
                }

                group.add((String)entry.getKey(), bean);
            }
        }

很明显第一次,这里没有做啥操作。这段代码主要把生命周期的bean加入生命周期gruop
还是认真的看了下这段代码发现这段代码写的很有艺术,首先用了迭代器,然后一个while一个do while,如果我写这段逻辑我会写个for循环,然后再if else还会嵌套,所以读源码还是有意义的。

总结

实例化配置文件主要就是为了以后的bean做铺垫,准备了一些资源,实例化崭新的beanfactory,初始化生命周期处理器,发布上下文刷新事件,最后注册了applicationContext。

是不是感觉实例化配置文件都没有提到bean的初始化,那么请看下篇文章。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring 实例化配置文件源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏