【spring】深入IOC

【spring】深入IOC

spring IOC容器封装了我们自定义的bean信息,为我们持有bean及管理bean的生命周期

IOC容器初始化过程包含bean信息的定位、载入和注册过程

要初始化IOC容器,首先需要对定义的bean信息进行定位,找到所需的bean信息
然后把这些bean信息载入到内存中

持有bean信息的数据结构是 BeanDefinition,封装了bean的所有基本属性
包括class,singleton,和bean所依赖的内部属性,如bean引用,各种value值等
而BeanDefinitionHolder 则封装了 BeanDefinition ,bean的名字和bean的别名组
这个beanDefinition 的持有与管理,是在DefaultListableBeanFactory 里维护的,
其中构建了一个 ConcurrentHashMap 来管理
/** Map of bean definition objects, keyed by bean name */
        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

//demo,通过 FileSystemXmlApplicationContext 构建IOC容器
//IOC容器就是持有和管理我们所需要的bean信息及其间的依赖关系的一个容器
// FileSystemXmlApplicationContext  就是通过查找文件系统信息寻找相关的bean信息定义文件
// ClassPathXmlApplicationContext 就是通过查找classpath路径寻找相关bean信息定义文件
// 两者在IOC容器的实现上是一致的,区别也就是路径查找上的一些不同而已 
public class SpringDemo5 {
    public static void main(String[] args) {
//        ApplicationContext context =
//                new ClassPathXmlApplicationContext("com\\ming\\ sns\\test\\bean-config.xml");
        ApplicationContext context =
                new FileSystemXmlApplicationContext( "src\\com\\ming\\sns\\test\\bean-config.xml" );
               //构建好容器后,通过getBean方法就可以获取到所需要的bean实例
        MyFactory2 test = (MyFactory2) context.getBean( "MyFactory2");
        test.show();
    }
}
//FileSystemXmlApplicationContext
//org.springframework.context.support.FileSystemXmlApplicationContext.class
// 构造方法中非常关键的方法是 refresh方法 。refresh函数 初始化context,整个IOC容器
// refresh方法启动整个IOC容器的初始化过程,包括bean信息的定位载入注册的过程
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
                   throws BeansException {
             super(parent);
            setConfigLocations(configLocations);
             if (refresh) {
                  refresh();
            }
      }
// 这是refresh方法的具体实现
//org.springframework.context.support.AbstractApplicationContext.class
public void refresh () throws BeansException, IllegalStateException {
             synchronized (this .startupShutdownMonitor ) {
                   // Prepare this context for refreshing.
                  prepareRefresh();
                   // Tell the subclass to refresh the internal bean factory.
                   // 获取BeanFactory 各种bean信息,及上下文信息就是在这个容器里维护的
                  ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                   // Prepare the bean factory for use in this context.
                  prepareBeanFactory(beanFactory);
                   try {
                         // Allows post-processing of the bean factory in context subclasses.
                        postProcessBeanFactory(beanFactory);
                         // Invoke factory processors registered as beans in the context.
                        invokeBeanFactoryPostProcessors(beanFactory);
                         // Register bean processors that intercept bean creation.
                        registerBeanPostProcessors(beanFactory);
                         // Initialize message source for this context.
                        initMessageSource();
                         // Initialize event multicaster for this context.
                        initApplicationEventMulticaster();
                         // Initialize other special beans in specific context subclasses.
                        onRefresh();
                         // Check for listener beans and register them.
                        registerListeners();
                         // Instantiate all remaining (non-lazy-init) singletons.
                        finishBeanFactoryInitialization(beanFactory);
                         // Last step: publish corresponding event.
                        finishRefresh();
                  }
                   catch (BeansException ex) {
                         // Destroy already created singletons to avoid dangling resources.
                        destroyBeans();
                         // Reset 'active' flag.
                        cancelRefresh(ex);
                         // Propagate exception to caller.
                         throw ex;
                  }
            }
      }
//org.springframework.context.support.AbstractApplicationContext.class
protected ConfigurableListableBeanFactory obtainFreshBeanFactory () {
                         // 这个方法非常重要,构建BeanFactory
            refreshBeanFactory();
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
             if (logger .isDebugEnabled()) {
                   logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
            }
             return beanFactory;
      }
org.springframework.context.support.AbstractRefreshableApplicationContext.class
protected final void refreshBeanFactory () throws BeansException {
                         // 把旧的容器清除
             if (hasBeanFactory()) {
                  destroyBeans();
                  closeBeanFactory();
            }
             try {
                 // 构建一个新的容器
                   // DefaultListableBeanFactory 为持有和管理上下文使用的IOC容器
                   // DefaultListableBeanFactory 里封装了所需要的数据结构,用以保存所需要的bean信息等
                  DefaultListableBeanFactory beanFactory = createBeanFactory();
                  beanFactory.setSerializationId(getId());
                  customizeBeanFactory(beanFactory);
                   // 载入所需要的bean信息
                  loadBeanDefinitions(beanFactory);
                   synchronized (this .beanFactoryMonitor ) {
                         this.beanFactory = beanFactory;
                  }
            }
             catch (IOException ex) {
                   throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
            }
      }
org.springframework.context.support.AbstractXmlApplicationContext.class
@Override
       protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
             // Create a new XmlBeanDefinitionReader for the given BeanFactory.
             // bean信息的载入是由一个reader类来执行,这里是XmlBeanDefinitionReader
              // XmlBeanDefinitionReader 能够读取并解析xml文件,把文件中的各类信息解析出来并载入到内存里
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
             // Configure the bean definition reader with this context's
             // resource loading environment.
            beanDefinitionReader.setEnvironment( this.getEnvironment());
            beanDefinitionReader.setResourceLoader( this);
            beanDefinitionReader.setEntityResolver( new ResourceEntityResolver(this ));
             // Allow a subclass to provide custom initialization of the reader,
             // then proceed with actually loading the bean definitions.
            initBeanDefinitionReader(beanDefinitionReader);
              // 信息载入的方法
            loadBeanDefinitions(beanDefinitionReader);
      }
// org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.class
/**
       * Process the given bean element, parsing the bean definition
       * and registering it with the registry.
       */
       protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
             // 解析xml中的元素,封装成一个BeanDefinition
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
             if (bdHolder != null) {
                  bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                   try {
                         // Register the final decorated instance.
                        BeanDefinitionReaderUtils. registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
                  }
                   catch (BeanDefinitionStoreException ex) {
                        getReaderContext().error( "Failed to register bean definition with name '" +
                                    bdHolder.getBeanName() + "'", ele, ex);
                  }
                   // Send registration event.
                  getReaderContext().fireComponentRegistered( new BeanComponentDefinition(bdHolder));
            }
      }
// org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.class
// bean信息解析和创建封装bean信息的具体方法实现
/**
       * Parse the bean definition itself, without regard to name or aliases. May return
       * <code>null</code> if problems occured during the parse of the bean definition.
       */
       public AbstractBeanDefinition parseBeanDefinitionElement (
                  Element ele, String beanName, BeanDefinition containingBean) {
             this.parseState .push(new BeanEntry(beanName));
            String className = null;
             if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
                  className = ele.getAttribute( CLASS_ATTRIBUTE).trim();
            }
             try {
                  String parent = null;
                   if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
                        parent = ele.getAttribute( PARENT_ATTRIBUTE);
                  }
                    // 创建一个封装bean信息的BeanDefinition类
                    // 其中非常重要的是bean的类对象信息,通过下面的语句进行设置
                    // bd.setBeanClass(ClassUtils.forName(className, classLoader));
                  // forName 方法里通过类加载构建bean类型的类对象
                    AbstractBeanDefinition bd = createBeanDefinition(className, parent);

                  // parseBeanDefinitionAttributes 方法用来设置bean的各种属性,如singleton
                  parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

                  bd.setDescription(DomUtils. getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT ));
                  parseMetaElements(ele, bd);
                  parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
                  parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
                  parseConstructorArgElements(ele, bd);
                   // 这里对bean 里的各个属性值进行解析并进行封装保存
                   // 如可能有 ref 引用,或者是value值,这些内容会被封装成PropertyValue值保存到BeanDefinition中
                  parsePropertyElements(ele, bd);
                  parseQualifierElements(ele, bd);
                  bd.setResource( this.readerContext .getResource());
                  bd.setSource(extractSource(ele));
                   return bd;
            }
             catch (ClassNotFoundException ex) {
                  error( "Bean class [" + className + "] not found" , ele, ex);
            }
             catch (NoClassDefFoundError err) {
                  error( "Class that bean class [" + className + "] depends on not found", ele, err);
            }
             catch (Throwable ex) {
                  error( "Unexpected failure during bean definition parsing", ele, ex);
            }
             finally {
                   this.parseState .pop();
            }
             return null ;
      }
// 如果bean信息里 有内部属性,就调用这个方法进行处理
// 内部属性包括,bean和list等结构元素
// 对于list 等集合元素,会构建并返回相关的集合对象,添加到Beandefinition中
/**
       * Parse a value, ref or collection sub -element of a property or
       * constructor -arg element.
       * @param ele subelement of property element; we don't know which yet
       * @param defaultValueType the default type (class name) for any
       * <code><value></code> tag that might be created
       */
       public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
             if (!isDefaultNamespace(ele)) {
                   return parseNestedCustomElement(ele, bd);
            }
             else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
                  BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
                   if (nestedBd != null) {
                        nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
                  }
                   return nestedBd;
            }
             else if (nodeNameEquals(ele, REF_ELEMENT)) {
                   // A generic reference to any name of any bean.
                  String refName = ele.getAttribute( BEAN_REF_ATTRIBUTE);
                   boolean toParent = false;
                   if (!StringUtils.hasLength(refName)) {
                         // A reference to the id of another bean in the same XML file.
                        refName = ele.getAttribute( LOCAL_REF_ATTRIBUTE);
                         if (!StringUtils.hasLength(refName)) {
                               // A reference to the id of another bean in a parent context.
                              refName = ele.getAttribute(PARENT_REF_ATTRIBUTE );
                              toParent = true;
                               if (!StringUtils.hasLength(refName)) {
                                    error( "'bean', 'local' or 'parent' is required for <ref> element", ele);
                                     return null ;
                              }
                        }
                  }
                   if (!StringUtils.hasText(refName)) {
                        error( "<ref> element contains empty target attribute", ele);
                         return null ;
                  }
                  RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
                  ref.setSource(extractSource(ele));
                   return ref;
            }
             else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
                   return parseIdRefElement(ele);
            }
             else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
                   return parseValueElement(ele, defaultValueType);
            }
             else if (nodeNameEquals(ele, NULL_ELEMENT)) {
                   // It's a distinguished null value. Let's wrap it in a TypedStringValue
                   // object in order to preserve the source location.
                  TypedStringValue nullHolder = new TypedStringValue(null );
                  nullHolder.setSource(extractSource(ele));
                   return nullHolder;
            }
             else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
                   return parseArrayElement(ele, bd);
            }
             else if (nodeNameEquals(ele, LIST_ELEMENT)) {
                   return parseListElement(ele, bd);
            }
             else if (nodeNameEquals(ele, SET_ELEMENT)) {
                   return parseSetElement(ele, bd);
            }
             else if (nodeNameEquals(ele, MAP_ELEMENT)) {
                   return parseMapElement(ele, bd);
            }
             else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
                   return parsePropsElement(ele);
            }
             else {
                  error( "Unknown property sub-element: [" + ele.getNodeName() + "]" , ele);
                   return null ;
            }
      }
// org.springframework.beans.factory.support.DefaultListableBeanFactory.class
// 在之前创建的BeanFactory 容器里注册 所解析到的 BeanDefinition信息
public void registerBeanDefinition (String beanName, BeanDefinition beanDefinition)
                   throws BeanDefinitionStoreException {
            Assert. hasText(beanName, "Bean name must not be empty");
            Assert. notNull(beanDefinition, "BeanDefinition must not be null");
             if (beanDefinition instanceof AbstractBeanDefinition) {
                   try {
                        ((AbstractBeanDefinition) beanDefinition).validate();
                  }
                   catch (BeanDefinitionValidationException ex) {
                         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                     "Validation of bean definition failed", ex);
                  }
            }
             synchronized (this .beanDefinitionMap ) {
                  Object oldBeanDefinition = this.beanDefinitionMap .get(beanName);
                   if (oldBeanDefinition != null) {
                         if (!this .allowBeanDefinitionOverriding ) {
                               throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                           "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                                           "': There is already [" + oldBeanDefinition + "] bound." );
                        }
                         else {
                               if (this .logger .isInfoEnabled()) {
                                     this.logger .info("Overriding bean definition for bean '" + beanName +
                                                 "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                              }
                        }
                  }
                   else {
                         this.beanDefinitionNames .add(beanName);
                         this.frozenBeanDefinitionNames = null;
                  }
                    // BeanDefinition 信息 最终是在一个map里保存的,保存格式是,bean的名字和封装了bean的各类信息的BeanDefinition结构
                   this.beanDefinitionMap .put(beanName, beanDefinition);
                  resetBeanDefinition(beanName);
            }
      }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值