Spring IOC总结

1.IOC容器初始化

(1)xmlBeanFactory的IOC容器流程

(2)FileSystemXmlApplicationContext 的IOC容器流程

2.IOC容器依赖注入

IOC容器初始化

IoC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本的过程。

一.xmlBeanFactory的IOC容器流程

BeanFactory b=new XmlBeanFactory(new ClassPathResource(“beanFactryTest.xml”));

xmlBeanFactory类真正实现资源加载是loanBeanDefinitions(resource)方法。

public class XmlBeanFactory extends DefaultListableBeanFactory{
     private final XmlBeanDefinitionReader reader;  
     public XmlBeanFactory(Resource resource)throws BeansException{       

  this(resource, null);   

  }     
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)          throws BeansException{         

super(parentBeanFactory);         

this.reader = new XmlBeanDefinitionReader(this);         

this.reader.loadBeanDefinitions(resource);    

}

}

 

//根据Xml配置文件创建Resource资源对象,该对象中包含了BeanDefinition的信息

 ClassPathResource resource =new ClassPathResource("application-context.xml");//创建DefaultListableBeanFactory

 DefaultListableBeanFactory factory =new DefaultListableBeanFactory();//创建XmlBeanDefinitionReader读取器,用于载入BeanDefinition。之所以需要BeanFactory作为参数,是因为会将读取的信息回调配置给factory

 XmlBeanDefinitionReader reader =new XmlBeanDefinitionReader(factory);//XmlBeanDefinitionReader执行载入BeanDefinition的方法,最后会完成Bean的载入和注册。完成后Bean就成功的放置到IOC容器当中,以后我们就可以从中取得Bean来使用

 reader.loadBeanDefinitions(resource);

 

1.loanBeanDefinitions方法实现:

(1)封装资源文件。当进入XmlBeanDefiniftionReader后首先对参数Resource使用EncodeResource类进行封装。

     loadBeanDefinitions(new EncodeResource(resource));

(2)获取输入流。从Resource中获取对应的ImputStream并构造InputSource.

     InputStream inputStream=encodeResource.getResource().getInputStream();

      InputSource inputSource=new InputSource(inputStream);

(3)通过构造的inputSource实例和Resource实例继续调用doLoadBeanDefinitions.

     doLoanBeanDefinitions(inputSource,encodedResource.getResource());

2.doLoanBeanDefinitions方法实现:

(1)获取对XML文件的验证模式。

代码:getValidationModeForResource(resource);

DTD:文档类型定义,包含元素的定义规则,元素间关系的定义规则,元素可使用属性,可使用实体或符号规则。检测XML文档格式是否符合规范,元素和标签使用是否正确。

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

XSD:描述了XML文档的结构。检测XML文档是否符合其要求。

<beans xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd”>

(2)加载XML文件,并得到对应的Document.

代码:

Documnet doc=this.documentLoader.loadDocumnet(inputSource,getEntityResolver(),

this.errorHandler,validationMode,isNamespaceAware());

获取Document首先创建DocumentBuilderFactory,在通过DocumentBuilderFactory创建DocumentBuilder,进而解析inputSource来返回Document对象。

DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);

DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);

Document=builder.parse(inputSource);

(3)根据返回的Document注册Bean信息。

代码:registerBeanDefinitions(doc,resource);

registerBeanDefinitions实现:

1.实例化documentReader

BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();

2.documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

registerBeanDefinitions实现:

调用doRegisterBeanDefinitions方法实现parseBeanDefitions(root,this.delegate);

parseBeanDefitions根据不同标签进行处理(import,alias,bean,beans)

二.FileSystemXmlApplicationContext 的IOC容器流程

ApplicationContext =new FileSystemXmlApplicationContext(xmlPath);

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)  

            throws BeansException {    

        super(parent);  

        setConfigLocations(configLocations);  

        if (refresh) {  

            refresh();  

        }  

    }

(super(parent)方法)为容器设置好Bean资源加载器

setConfigLocations(configLocations)方法设置Bean定义资源文件的定位路径。

Spring IoC容器对Bean定义资源的载入是从refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入。

refresh方法实现:

public void refresh() throws BeansException, IllegalStateException {  

        synchronized (this.startupShutdownMonitor) {  

            //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识  

            prepareRefresh();              

//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从    

         //子类的refreshBeanFactory()方法启动

             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  

            //为BeanFactory配置容器特性,例如类加载器、事件处理器等

            prepareBeanFactory(beanFactory);  

            try {  

               //为容器的某些子类指定特殊的BeanPost事件处理器  

                postProcessBeanFactory(beanFactory);  

                //调用所有注册的BeanFactoryPostProcessor的Bean  

                invokeBeanFactoryPostProcessors(beanFactory);  

                //为BeanFactory注册BeanPost事件处理器.  

               //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件  

                registerBeanPostProcessors(beanFactory);  

                //初始化信息源,和国际化相关.

                initMessageSource();  

                //初始化容器事件传播器.  

                initApplicationEventMulticaster();  

                //调用子类的某些特殊Bean初始化方法  

                onRefresh();  

                //为事件传播器注册事件监听器.  

               registerListeners();  

                //初始化所有剩余的单态Bean.  

                finishBeanFactoryInitialization(beanFactory);  

                //初始化容器的生命周期事件处理器,并发布容器的生命周期事件  

                finishRefresh();  

            }  

            catch (BeansException ex) {  

                //销毁以创建的单态Bean  

                destroyBeans();  

                //取消refresh操作,重置容器的同步标识.  

               cancelRefresh(ex);  

                throw ex;  

            }  

       }  

    }

“ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();”这句以后代码的都是注册容器的信息源和生命周期事件,载入过程就是从这句代码启动。

obtainFreshBeanFactory实现

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {  

        //这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的         //refreshBeanFactory()方法         

        refreshBeanFactory();  

        ConfigurableListableBeanFactory beanFactory = getBeanFactory();  

        if (logger.isDebugEnabled()) {  

            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);  

        }  

        return beanFactory;  

    }

 protected final void refreshBeanFactory() throws BeansException {    

if (hasBeanFactory()) {//如果已经有容器,销毁容器中的bean,关闭容器

             destroyBeans();

           closeBeanFactory();        

 }         

try {  

            //创建IoC容器  

             DefaultListableBeanFactory beanFactory = createBeanFactory();  

            beanFactory.setSerializationId(getId());  

            //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等  

            customizeBeanFactory(beanFactory);  

            //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器

             loadBeanDefinitions(beanFactory);  

           synchronized (this.beanFactoryMonitor) {  

               this.beanFactory = beanFactory;  

           }

         }

         catch (IOException ex) {      

throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);  

        }  

   }

 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {

         //创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容  器使用该读取器读取Bean定义资源  

         XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);  

         //为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的  

         //祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器  

        beanDefinitionReader.setResourceLoader(this);  

        //为Bean读取器设置SAX xml解析器  

        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));  

        //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制  

        initBeanDefinitionReader(beanDefinitionReader);  

        //Bean读取器真正实现加载的方法

         loadBeanDefinitions(beanDefinitionReader);  

    }

     //Xml Bean读取器加载Bean定义资源  

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {  20        //获取Bean定义资源的定位  

        Resource[] configResources = getConfigResources();  

        if (configResources != null) {  

            //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位

             //的Bean定义资源

             reader.loadBeanDefinitions(configResources);  

       }        

 //如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源

         String[] configLocations = getConfigLocations();  

        if (configLocations != null) {

             //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位  

           //的Bean定义资源  

           reader.loadBeanDefinitions(configLocations);  

        }  

    }  

    //这里又使用了一个委托模式,调用子类的获取Bean定义资源定位的方法  

    //该方法在ClassPathXmlApplicationContext中进行实现,对于我们  

    //举例分析源码的FileSystemXmlApplicationContext没有使用该方法  

    protected Resource[] getConfigResources() {  

        return null;  

    }

//重载方法,调用下面的loadBeanDefinitions(String, Set<Resource>);方法  

    public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {  

       return loadBeanDefinitions(location, null);  

    }  

   public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {  

        //获取在IoC容器初始化过程中设置的资源加载器  

        ResourceLoader resourceLoader = getResourceLoader();  

        if (resourceLoader == null) {  

            throw new BeanDefinitionStoreException(  

                    "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");  

        }  

        if (resourceLoader instanceof ResourcePatternResolver) {  

            try {  

                //将指定位置的Bean定义资源文件解析为Spring IoC容器封装的资源  

                //加载多个指定位置的Bean定义资源文件  

               Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);  17                //委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能  

                int loadCount = loadBeanDefinitions(resources);

                if (actualResources != null) {  

                    for (Resource resource : resources) {

                        actualResources.add(resource);  

                  }  

                }

                if (logger.isDebugEnabled()) {  

                    logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");  

               }

                return loadCount;  

           }  

           catch (IOException ex) {  

               throw new BeanDefinitionStoreException(  

                       "Could not resolve bean definition resource pattern [" + location + "]", ex);             }

         }  

       else {  

            //将指定位置的Bean定义资源文件解析为Spring IoC容器封装的资源

             //加载单个指定位置的Bean定义资源文件

             Resource resource = resourceLoader.getResource(location);  

           //委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能  

           int loadCount = loadBeanDefinitions(resource);  

            if (actualResources != null) {  

                actualResources.add(resource);

            }  

            if (logger.isDebugEnabled()) {  

                logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");  

            }  

           return loadCount;  

        }  

    }

     //重载方法,调用loadBeanDefinitions(String);  

    public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {  

        Assert.notNull(locations, "Location array must not be null");

         int counter = 0;  

        for (String location : locations) {

             counter += loadBeanDefinitions(location);  

        }  

        return counter;  

    }

//获取Resource的具体实现方法  

public Resource getResource(String location) {  

        Assert.notNull(location, "Location must not be null");  

        //如果是类路径的方式,那需要使用ClassPathResource 来得到bean 文件的资源对象  

        if (location.startsWith(CLASSPATH_URL_PREFIX)) {  

            return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());          }  

         try {  

              // 如果是URL 方式,使用UrlResource 作为bean 文件的资源对象  

             URL url = new URL(location);  

             return new UrlResource(url);  

            }  

            catch (MalformedURLException ex) {

            }

            //如果既不是classpath标识,又不是URL标识的Resource定位,则调用  

           //容器本身的getResourceByPath方法获取Resource  

            return getResourceByPath(location);  

           

   }

protected Resource getResourceByPath(String path) {     

  if (path != null && path.startsWith("/")) {          

  path = path.substring(1);       

 }      //这里使用文件系统资源对象来定义bean 文件

    return new FileSystemResource(path);  

}

 

IOC容器依赖注入

MyTestBean bean=(MyTestBean) bf.getBean(“meTestBean”);

getBean方法的doGetBean

方法里包含:

1.存在缓存

(1)getSingleton方法:缓存中获取单例bean

     SingletonObjects:一级缓存,先从此中获取实例

     earlySingletonObjects:二级缓存,如果一级缓存获取不到实例,再从此种获取实例

     singletonFactories:三级缓存,如果二级缓存获取不到实例,再从此种获取实例

(2)getObjectForBeanInstance方法:从bean的实例中获取对象

     对FactoryBean正确性的验证。

     对非FactoryBean不做任何处理。

     对bean进行转换。

     将从Factory中解析bean的工作委托给GetObjectFromFactoryBean.

     GetObjectFromFactoryBean:返回的bean如果是单例的,那就必须要保证全局唯一,同时因为是单例的,所以不必重复创建,可以使用缓存来提高性能。

     doGetObjectFromFactoryBean方法:

     factory.getObject();

     postProcessObjectFromFactoryBean

2.无缓存:

(1)getSingleton方法:检查缓存是否已经加载过,若没有加载,则记录beanName的正在加载状态。

     beforeSingletonCreation:加载单例前记录加载状态.

     singletonFactory.getObject();:实例化bean

     afterSingletonCreation:加载单例后处理方法调用,即移除缓存中对该bean正在加载状态的记录。

     addSingleton:将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态。

3.准备创建bean

  CreateBean方法:

   resolveBeanClass:根据设置的class属性或者根据className来解析Class.

   mbd.prepareMethodOverrides:验证及准备覆盖的方法。对Override属性进行标记及验证。

   resolveBeforeInstantiation:给beanProcessors一个机会来返回代理来替代真正的实例。应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作。

   docreateBean:创建bean

循环依赖

4.创建bean

docreateBean方法:

(1)createBeanInstance方法:

  AutowireConstructor:带参数构造函数实例化

  instantiateBean:不带参数构造函数实例化

  循环依赖检查。

(2)populateBean方法:

InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation函数的应用,此函数可以控制程序是否继续进行属性填充。

autowireByName:属性注入(根据名称自动注入)

autowireByType:属性注入(根据类型自动注入)

InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理。

ApplyPropertyValues:将所有propertyValues中的属性填充至BeanWrapper.

(3)initializeBean:调用用户设置的初始化方法。

(4)registerDisposableBeanIfNecessary:注册后处理器来统一处理bean的销毁方法。

转载于:https://my.oschina.net/yangfeima/blog/889746

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值