Spring IOC容器初始化

一、IOC容器结构体系

日常工作中常用的spring框架,极大的简化了java程序员的开发,很多时候我们只关心怎么用,但是作为一名专业的程序员,对spring源码的学习还是必不可少的,学习spring源码对我们日常开发的帮助无疑是巨大的,能够提升大家的开发思维模式,好了,接下来让我们来看看Spring IOC容器初始化流程具体是如何实现的。

  1. 首先介绍一下spring容器的类层次结构图:其中顶层容器接口BeanFactory,我们用到的最多的接口是ApplicationContext,常用实现类有ClassPathXmlApplicationContext、AnnotationConfigApplicationContext、FileSystemXmlApplicationContext、web开发中对应的实现类有AnnotationConfigWebApplicationContext,也就是springmvc容器,至于springmvc容器初始化等过程在本文不再过多的描述了。
    IOC容器结构

二、从最基本的 ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“applicationContext.xml”);作为入口开始分析整个IOC容器初始化过程。

  1. ClassPathXmlApplicationContext构造函数:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
        super(parent);
        this.setConfigLocations(configLocations);
        if (refresh) {
            this.refresh();
        }
    }
//由构造函数可以锁定初始化IOC容器的核心方法为refresh方法,接下来我们跟进refresh方法。
 public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
        	//容器刷新准备工作
            this.prepareRefresh();
            //创建beanFactory,加载配置文件,创建beanDefinition等
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //为beanFactory设置一些需要设置的参数
            this.prepareBeanFactory(beanFactory);
            try {
            	//创建postProcessBeanFactory
                this.postProcessBeanFactory(beanFactory);
                //调用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();
            }

        }
    }

refresh方法是由父类AbstractApplicationContext实现,该方法制定了整体的流程结构,某些步骤可以交给子类来具体实现,接下来逐步讲解每个方法中的实现逻辑和思想。

  1. prepareRefresh()方法:该方法主要进行容器初始化的准备工作。
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());
            }
        }
        //初始化属性资源,用于初始化web应用中的servlet属性等
        this.initPropertySources();
        //设置ioc容器环境并校验,该方法内部调用了ConfigurablePropertyResolver.validateRequiredProperties()来校验
        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();
    }
  1. obtainFreshBeanFactory():创建并刷新BeanFactory工厂,该方法由子类:AbstractRefreshableApplicationContext实现
protected final void refreshBeanFactory() throws BeansException {
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
        //默认创建DefaultListableBeanFactory ,该类实现了容器顶层接口BeanFactory
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            //beanFactory设置org.springframework.context.support.ClassPathXmlApplicationContext@77e9807f的地址值
            beanFactory.setSerializationId(this.getId());
            //该方法中为beanFactory设置是否开启自定义的beanDefinition
            this.customizeBeanFactory(beanFactory);
            //该方法由子类AbstractXmlApplicationContext实现,负责加载解析xml配置文件并构建出beanDefinition,下面详细介绍该方法
            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);
        }
    }

1.1.0. loadBeanDefinitions(beanFactory),该方法加载解析配置文件并构建出BeanDefinition:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//创建beanDefinitionReader,里面调用了父类的super(registry);
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        //设置ioc容器资源环境
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        //设置资源加载类为this(实现了ResourceLoader,可以加载资源)
        beanDefinitionReader.setResourceLoader(this);
        //设置实体解析器
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        //初始化beanDefinitionReader
        this.initBeanDefinitionReader(beanDefinitionReader);
        //真正的加载beanDefinitionReader,进入该方法解析
        this.loadBeanDefinitions(beanDefinitionReader);
    }

XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
        super(registry);
        this.errorHandler = new SimpleSaxErrorHandler(this.logger);
        this.validationModeDetector = new XmlValidationModeDetector();
        this.resourcesCurrentlyBeingLoaded = new NamedThreadLocal("XML bean definition resources currently being loaded");
    }

父类的构造函数里设置了默认的资源加载器:this.resourceLoader = new DefaultResourceLoader();并设置了默认的Environment:this.environment = new StandardEnvironment();

1.1.1. this.loadBeanDefinitions(beanDefinitionReader);

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		//得到配置的资源,默认返回null
        Resource[] configResources = this.getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
		//得到applicationContext.xml配置文件
        String[] configLocations = this.getConfigLocations();
        if (configLocations != null) {
        	//真正加载资源配置文件,调用AbstractBeanDefinitionReader类的loadBeanDefinitions方法解析配置文件并构建beanDefinition
            reader.loadBeanDefinitions(configLocations);
        }
    }

1.1.2. AbstractBeanDefinitionReader.loadBeanDefinitions(configLocations)

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		//该资源加载器之前设置为了org.springframework.context.support.ClassPathXmlApplicationContext@77e9807f
        ResourceLoader resourceLoader = this.getResourceLoader();
        if (resourceLoader == null) {
            throw new BeanDefinitionStoreException("Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
        } else {
            int count;
            if (resourceLoader instanceof ResourcePatternResolver) {
                try {
                //加载applicationContext.xml资源为Resource,getResources的最终实现是在PathMatchingResourcePatternResolver里,该方法主要是记载资源,就不再详细介绍
                    Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
                    //真正加载资源的方法:,该方法内部调用了XmlBeanDefinitionReader.doLoadBeanDefinitions方法,下面介绍该方法
                    count = this.loadBeanDefinitions(resources);
                    if (actualResources != null) {
                        Collections.addAll(actualResources, resources);
                    }

                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
                    }

                    return count;
                } catch (IOException var6) {
                    throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var6);
                }
            } else {
                Resource resource = resourceLoader.getResource(location);
                count = this.loadBeanDefinitions((Resource)resource);
                if (actualResources != null) {
                    actualResources.add(resource);
                }

                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
                }

                return count;
            }
        }
    }

1.1.3:XmlBeanDefinitionReader.doLoadBeanDefinitions方法

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
        	//将资源加载为w3c规范的Document结构
            Document doc = this.doLoadDocument(inputSource, resource);
            //将各个节点封装为beanDefinition,最后真正向IOC容器注册beanDefinition
            int count = this.registerBeanDefinitions(doc, resource);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Loaded " + count + " bean definitions from " + resource);
            }
            return count;
        }

到这里obtainFreshBeanFactory();方法就走完了,接下来看this.prepareBeanFactory(beanFactory);方法;

三、this.prepareBeanFactory(beanFactory):该方法主要对beanFactory做一些设置属性等操作。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		 设置beanFactory的classLoader为当前context的classLoader
        beanFactory.setBeanClassLoader(this.getClassLoader());
        设置beanFactory的表达式语言处理器,spring 3增加了表达式语言的支持
        //默认可以使用#{bean.xxx}的形式来调用相关的属性
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
       	 //为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性等设置管理一个工具
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
        // 添加BeanPostProcessor
        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));
         //增加了对AspectJ的支持
        if (beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
		//添加默认的系统环境bean
        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)…就不再本节分析了,可以查看后续章节。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值