死磕spring源码五遍,十遍--解析注册

spring很是重要,所以就是干!

阅读spring源码的时候这三个模块尤其中要,因为是初学,所以

首先重点关注这三个模块

接下来就是开始搭建阅读spring源码的环境在idea 中用maven直接在github拉取

https://github.com/spring-projects/spring-framework

然后在idea terminal预编译直接下面的命令

./gradlew :spring-oxm:compileTestJava
出现就有了阅读环境

1.org.springframework.core.io.Resource 为 Spring 框架所有资源的抽象和访问接口

要得到xml里面的bean信息首先要对配置文件进行分装,也就是得到资源文件。

接下来就是资源文件的读取。交给了一个类XmlBeanDefinitionReader这个类才是对资源文件的加载。

加载需要调用XmlBeanDefinitionReader类中的loadBeanDefinitions方法。

BeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

加载的时候需要判断解析,这个文件的内容分时,重要的是bean的解析,但是要有承载bean属性信息的东西,这个就是BeanDefinition。

期间还要涉及到xml文件的验证......(建议初学者先熟悉流程之后在慢慢看)
Document doc = this.doLoadDocument(inputSource, resource);//得到配置文件的doc属性(建议初学者先熟悉流程之后在慢慢看)
return this.registerBeanDefinitions(doc, resource);//根据获取的 Document 实例,注册 Bean 信息

注册就是通过BeanDefinitionRegistry接口将bean注册到容器中beanFactory,在spring环境下所有用到的所有bean都需要在spring容器中。

重点分析:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {

//创建 BeanDefinitionDocumentReader 对象
    1BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
//得到已注册的 BeanDefinition 数量
    2int countBefore = this.getRegistry().getBeanDefinitionCount();
//创建 XmlReaderContext 对象       加载注册 BeanDefinition
    3documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
//记录加载BeanDefinition的个数
    4return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
(1)//通过类反射工具实例化BeanDefinitionDocumentReader对象
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    return (BeanDefinitionDocumentReader)BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}

(2)在DefaultBeanDefinitionDocumentReader里找到实现得到配置文件root属性(注册)

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    this.logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();
    this.doRegisterBeanDefinitions(root);
}

doRegisterBeanDefinitions方法(继续注册 真正的注册也是 解析元素)

protected void doRegisterBeanDefinitions(Element root) {
//BeanDefinitionParserDelegate 解析BeanDefinition

    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
    if(this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute("profile");
        if(StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
            if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if(this.logger.isInfoEnabled()) {
                    this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
                }

                return;
            }
        }
    }

    this.preProcessXml(root);
    this.parseBeanDefinitions(root, this.delegate);
    this.postProcessXml(root);
    this.delegate = parent;
}
//解析beandefinition
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if(delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();

        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            if(node instanceof Element) {
                Element ele = (Element)node;
                if(delegate.isDefaultNamespace(ele)) {//如果该节点使用默认命名空间,执行默认解析
                    this.parseDefaultElement(ele, delegate);
                } else {
                    delegate.parseCustomElement(ele);//解析默认标签
                }
            }
        }
    } else {
        delegate.parseCustomElement(root);//解析自定义标签
    }

}
//解析默认标签

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    if(delegate.nodeNameEquals(ele, "import")) {//解析import标签
        this.importBeanDefinitionResource(ele);
    } else if(delegate.nodeNameEquals(ele, "alias")) {//解析alias标签
        this.processAliasRegistration(ele);
    } else if(delegate.nodeNameEquals(ele, "bean")) {解析bean标签
        this.processBeanDefinition(ele, delegate);
    } else if(delegate.nodeNameEquals(ele, "beans")) {
        this.doRegisterBeanDefinitions(ele);
    }

}

默认标签bean的解析

bean标签解析

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
  (1) BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
     (2) bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);.//对自定义标签的解析
      try {
         // 对bdHolder进行注册
        (3) 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));
   }
}

(1)解析的过程中会创建承载bean属性的BeanDefinitaion

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {

return parseBeanDefinitionElement(ele, null);

}

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
}

public AbstractBeanDefinition parseBeanDefinitionElement(){
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
}
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
      throws ClassNotFoundException {

   return BeanDefinitionReaderUtils.createBeanDefinition( parentName, className,    this.readerContext.getBeanClassLoader());
}
public static AbstractBeanDefinition createBeanDefinition(
      String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {

   GenericBeanDefinition bd = new GenericBeanDefinition();//进一步封装在GenericBeanDefinition中
   bd.setParentName(parentName);
   if (className != null) {
      if (classLoader != null) {
         bd.setBeanClass(ClassUtils.forName(className, classLoader));
      }
      else {
         bd.setBeanClassName(className);
      }
   }

其中AbstractBeanDefinition bd类型已经变为GenericBeanDefinition类型

public class GenericBeanDefinition extends AbstractBeanDefinition 

bd里面同过set方法存放了bean的各种子属性元素

(2)bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//注册自定义的标签

解析了配置文件里面的各种标签下面就开始注册解析的BeanDefinition,也就是上面提过的

(3) BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // Register bean definition under primary name.
   String beanName = definitionHolder.getBeanName();
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // Register aliases for bean name, if any.
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String aliase : aliases) {
         registry.registerAlias(beanName, aliase);
      }
   }
}

注意最终奥义BeanDefinitionRegistry 实现了注册beanDefinition()

完结。

可以通过名字和别名注册

(1)通过名字注册

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
      implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
this.beanDefinitionMap.put(beanName, beanDefinition);//将beanName 和beanDefiniton放在map中

/*

具体实现看源码

*/

 

}

具体实现功能

BeanDefinition 的缓存也不是神奇的东西,就是定义一个 Map :

  • key 为 beanName 。
  • value 为 BeanDefinition 对象。

注册就是注册装有BeanDefinition 对象的map缓存中。

实现了BeanDefinitionRegistry接口中的

void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
Private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
this.beanDefinitionMap.put(beanName, beanDefinition);//bean注册真相

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ioc容器

  • 在 IoC 容器内部维护着一个 BeanDefinition Map 的数据结构
  • 在配置文件中每一个 <bean> 都对应着一个 BeanDefinition 对象。

 

  • 注册。向 IoC 容器注册在第二步解析好的 BeanDefinition,这个过程是通过
     

  •  

  •  

  •  

  • 接口来实现的。在 IoC 容器内部其实是将第二个过程解析得到的 BeanDefinition 注入到一个 HashMap 容器中,IoC 容器就是通过这个 HashMap 来维护这些 BeanDefinition 的。

  • 在这里需要注意的一点是这个过程并没有完成依赖注入,依赖注册是发生在应用第一次调用 #getBean(...) 方法,向容器索要 Bean 时。
  • 当然我们可以通过设置预处理,即对某个 Bean 设置 lazyinit = false 属性,那么这个 Bean 的依赖注入就会在容器初始化的时候完成。

 

注册beanDefiniiton的时候会解析标签默认标签和自定义标签

 protected void doRegisterBeanDefinitions(Element root) {
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
        if(this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute("profile");
            if(StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
                if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if(this.logger.isInfoEnabled()) {
                        this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
                    }

                    return;
                }
            }
        }

        this.preProcessXml(root);
        this.parseBeanDefinitions(root, this.delegate);
        this.postProcessXml(root);
        this.delegate = parent;
    }

再次强调:

beandefiniiton中包含了一些配置文件中的一些标签属性

注册beandefiniiton就是 将beanDefiniton加入spring中ioc容器中

这里是解析资源文件的bean 默认标签

 


包扫描是解析自定义标签:
 

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    String namespaceUri = this.getNamespaceURI(ele);//获取标签的命名空间
根据名称空间找到对应的NamespaceHandler 
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if(handler == null) {
        this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    } else {
//标签解析
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }
}

对于parse()方法

NamespaceHandlerSupport.java
public BeanDefinition parse(Element element, ParserContext parserContext) {
        return this.findParserForElement(element, parserContext).parse(element, parserContext);
    }


AbstractBeanDefinitionParser.java
 public final BeanDefinition parse(Element element, ParserContext parserContext) {
        AbstractBeanDefinition definition = this.parseInternal(element, parserContext);
}

 protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        String parentName = this.getParentName(element);
        if(parentName != null) {
            builder.getRawBeanDefinition().setParentName(parentName);
        }

        Class<?> beanClass = this.getBeanClass(element);
        if(beanClass != null) {
            builder.getRawBeanDefinition().setBeanClass(beanClass);
        } else {
            String beanClassName = this.getBeanClassName(element);
            if(beanClassName != null) {
                builder.getRawBeanDefinition().setBeanClassName(beanClassName);
            }
        }

        builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
        if(parserContext.isNested()) {
            builder.setScope(parserContext.getContainingBeanDefinition().getScope());
        }

        if(parserContext.isDefaultLazyInit()) {
            builder.setLazyInit(true);
        }

        this.doParse(element, parserContext, builder);
        return builder.getBeanDefinition();
    }

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值