zoukankan      html  css  js  c++  java
  • Spring IOC源码实现流程

    最近一段时间学习了IOC的源码实现,分享一下大概流程

    创建一个测试类 代码如下:

    package com.zcg.learn.Test;

    import org.junit.Test;
    import org.springframework.beans.factory.support.AbstractBeanDefinition;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;

    import com.zcg.learn.UserDaoImpl;
    import com.zcg.learn.UserServiceImpl;
    /**
    * spring源码测试类
    * @author zcg
    * 2019/2/1
    *
    */
    public class BeanFactoryTest {

    @Test
    public void createBeanTest() {
    DefaultListableBeanFactory factory= new DefaultListableBeanFactory();
    UserServiceImpl bean = factory.createBean(UserServiceImpl.class);
    System.out.println(bean);
    }

    /**
    * bean的存储
    */
    @Test
    public void beanStoreTest() {
    DefaultListableBeanFactory factory= new DefaultListableBeanFactory();
    //单例模式的bean的存储
    factory.registerSingleton("userServiceImpl", new UserServiceImpl());
    UserServiceImpl userServiceImpl = (UserServiceImpl) factory.getBean("userServiceImpl");
    System.out.println(userServiceImpl+"====");

    userServiceImpl.addUser();
    }

    /**
    * 依赖关系的注入
    */
    @Test
    public void dependcsTest() {
    DefaultListableBeanFactory factory= new DefaultListableBeanFactory();
    factory.registerSingleton("userDao", new UserDaoImpl());
    UserServiceImpl userServiceImpl = (UserServiceImpl) factory.createBean(UserServiceImpl.class,
    AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);

    System.out.println(userServiceImpl+"====");

    userServiceImpl.addUser();
    }

    @Test
    public void getBeanTest() {
    DefaultListableBeanFactory factory= new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions("spring.xml");
    UserServiceImpl bean = factory.getBean(UserServiceImpl.class);
    //UserServiceImpl bean1 = (UserServiceImpl) factory.getBean("111");
    System.out.println("得到的bean"+bean);
    }
    }


    @Test
    public void getBeanTest() {
    DefaultListableBeanFactory factory= new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions("spring.xml");
    UserServiceImpl bean = factory.getBean(UserServiceImpl.class);
    //UserServiceImpl bean1 = (UserServiceImpl) factory.getBean("111");
    System.out.println("得到的bean"+bean);
    }这个方法分析下

    首先看下BeanDefinition的加载,解析和注册过程

    1.在AbstractBeanDefinitionReader类中将文件位置转换成resource 具体代码如下

    public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
    throw new BeanDefinitionStoreException(
    "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
    // Resource pattern matching available.
    try {

    //将位置对应的文件转换成 resources,并执行loadBeanDefinitions(resources)
    Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
    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 {
    // Can only load single resources by absolute URL.
    Resource resource = resourceLoader.getResource(location);
    int loadCount = loadBeanDefinitions(resource);
    if (actualResources != null) {
    actualResources.add(resource);
    }
    if (logger.isDebugEnabled()) {
    logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
    }
    return loadCount;
    }
    }

    2.在XmlBeanDefinitionReader类中加载文件 loadBeanDefinitions(resources)具体代码如下

    @Override
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
    }

    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
    logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
    currentResources = new HashSet<EncodedResource>(4);
    this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
    throw new BeanDefinitionStoreException(
    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {

    //得到输入流
    InputStream inputStream = encodedResource.getResource().getInputStream();
    try {
    InputSource inputSource = new InputSource(inputStream);
    if (encodedResource.getEncoding() != null) {

    //对输入流设置编码
    inputSource.setEncoding(encodedResource.getEncoding());
    }
    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    finally {
    inputStream.close();
    }
    }
    catch (IOException ex) {
    throw new BeanDefinitionStoreException(
    "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
    currentResources.remove(encodedResource);
    if (currentResources.isEmpty()) {
    this.resourcesCurrentlyBeingLoaded.remove();
    }
    }
    }

    其中 doLoadBeanDefinitions(inputSource, encodedResource.getResource())具体访问如下:

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {
    try {

    //将输入流转换成Document
    Document doc = doLoadDocument(inputSource, resource);

    //对doc进行注入
    return registerBeanDefinitions(doc, resource);

    }
    catch (BeanDefinitionStoreException ex) {
    throw ex;
    }
    catch (SAXParseException ex) {
    throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
    }
    catch (SAXException ex) {
    throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    "XML document from " + resource + " is invalid", ex);
    }
    catch (ParserConfigurationException ex) {
    throw new BeanDefinitionStoreException(resource.getDescription(),
    "Parser configuration exception parsing XML from " + resource, ex);
    }
    catch (IOException ex) {
    throw new BeanDefinitionStoreException(resource.getDescription(),
    "IOException parsing XML document from " + resource, ex);
    }
    catch (Throwable ex) {
    throw new BeanDefinitionStoreException(resource.getDescription(),
    "Unexpected exception parsing XML document from " + resource, ex);
    }
    }

     doLoadDocument(inputSource, resource)主要代码如下:

    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
    getValidationModeForResource(resource), isNamespaceAware());
    }

    3.loadDocument方法主要是调用DefaultDocumentLoader类中的方法 

    public class DefaultDocumentLoader implements DocumentLoader {

    /**
    * Load the {@link Document} at the supplied {@link InputSource} using the standard JAXP-configured
    * XML parser.
    * inputSource 接收的文件流
    * 加载转换成document
    */
    @Override
    public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
    ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

    DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    if (logger.isDebugEnabled()) {
    logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
    }
    DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
    //转换成文档
    return builder.parse(inputSource);
    }

    }

    4.registerBeanDefinitions(doc, resource)方法主要代码  如下

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
    }

    documentReader.registerBeanDefinitions(doc, createReaderContext(resource))主要是DefaultBeanDefinitionDocumentReader类下的方法 

    public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

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

    //对解析的doc的root元素进行注册

    protected void doRegisterBeanDefinitions(Element root) {

    // Any nested <beans> elements will cause recursion in this method. In
    // order to propagate and preserve <beans> default-* attributes correctly,
    // keep track of the current (parent) delegate, which may be null. Create
    // the new (child) delegate with a reference to the parent for fallback purposes,
    // then ultimately reset this.delegate back to its original (parent) reference.
    // this behavior emulates a stack of delegates without actually necessitating one.
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

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

    preProcessXml(root);

    // 对root解析成BeanDefinitions
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);

    this.delegate = parent;
    }

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {

    // 得到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)) {
    //解析Element 
    parseDefaultElement(ele, delegate);
    }
    else {
    delegate.parseCustomElement(ele);
    }
    }
    }
    }
    else {
    delegate.parseCustomElement(root);
    }
    }

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {

    //解析import标签
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
    importBeanDefinitionResource(ele);
    }

    //解析alias标签
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
    processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
    //解析bean
    processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
    //解析beans标签,就是进行递归解析
    doRegisterBeanDefinitions(ele);
    }
    }

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {

    //将Element 转换成 BeanDefinitionHolder 
    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));
    }
    }

    }

    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())是BeanDefinitionReaderUtils类下的方法  核心代码如下

    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 alias : aliases) {
    registry.registerAlias(beanName, alias);
    }
    }
    }

    5.registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());主要是DefaultListableBeanFactory 类对解析好点的BeanDefinition进行注入到facotry中

    @SuppressWarnings("serial")
    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    @Override
    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);
    }
    }

    BeanDefinition oldBeanDefinition;

    oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    if (oldBeanDefinition != null) {
    if (!isAllowBeanDefinitionOverriding()) {
    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
    "': There is already [" + oldBeanDefinition + "] bound.");
    }
    else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
    // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    if (this.logger.isWarnEnabled()) {
    this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
    "' with a framework-generated bean definition: replacing [" +
    oldBeanDefinition + "] with [" + beanDefinition + "]");
    }
    }
    else if (!beanDefinition.equals(oldBeanDefinition)) {
    if (this.logger.isInfoEnabled()) {
    this.logger.info("Overriding bean definition for bean '" + beanName +
    "' with a different definition: replacing [" + oldBeanDefinition +
    "] with [" + beanDefinition + "]");
    }
    }
    else {
    if (this.logger.isDebugEnabled()) {
    this.logger.debug("Overriding bean definition for bean '" + beanName +
    "' with an equivalent definition: replacing [" + oldBeanDefinition +
    "] with [" + beanDefinition + "]");
    }
    }
    this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
    if (hasBeanCreationStarted()) {
    // Cannot modify startup-time collection elements anymore (for stable iteration)
    synchronized (this.beanDefinitionMap) {
    this.beanDefinitionMap.put(beanName, beanDefinition);
    List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
    updatedDefinitions.addAll(this.beanDefinitionNames);
    updatedDefinitions.add(beanName);
    this.beanDefinitionNames = updatedDefinitions;
    if (this.manualSingletonNames.contains(beanName)) {
    Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
    updatedSingletons.remove(beanName);
    this.manualSingletonNames = updatedSingletons;
    }
    }
    }
    else {
    // Still in startup registration phase
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
    this.manualSingletonNames.remove(beanName);
    }
    this.frozenBeanDefinitionNames = null;
    }

    if (oldBeanDefinition != null || containsSingleton(beanName)) {
    resetBeanDefinition(beanName);
    }
    }

    }

  • 相关阅读:
    pinpoint改造支持查询
    pinpoint本地开发——agent
    pinpoint本地开发——collector
    pinpoint本地开发-web模块
    第一个Vert.x程序
    ls bash: cannot create temp file for here-document: No space left on device
    hadoop磁盘空间不均衡的解决办法
    dubbo监控活跃线程数
    mac安装软件运行提示「xxx.app已损坏,打不开.你应该将它移到废纸篓」的解决办法
    python拆分excel脚本
  • 原文地址:https://www.cnblogs.com/zcg1051980588/p/10474605.html
Copyright © 2011-2022 走看看