关于spring:SpringBean的几个问题以及原理

59次阅读

共计 4685 个字符,预计需要花费 12 分钟才能阅读完成。

一、几个问题

  1. Spring 中的 bean 是如何生成?
  2. Spring 提供了哪些扩大点能够整合第三方框架
  3. Spring 如何整合 Mybatis 的

二、什么是 Spring

Spring 治理 bean(Java 中的对象),初始化的操作,

三、Spring IoC 容器

  1. 资源组件:

    Resource,对资源文件的形容,不同资源文件如 xml、properties 文件等,格局不同,最终都将被 ResourceLoader 加载取得相应的 Resource 对象;集体了解是。主配置文件. 主配置作为所有配置的入口

  2. 资源加载组件:

    ResourceLoader:加载 xml、properties 等各类格式文件,解析文件,并生成 Resource 对象。加载哪些解析过的配置资源

  3. Bean 容器组件:

    BeanFactory 体系:IoC 容器的外围,其余组件都是为它工作的(但不是仅仅为其服务). 外围

  4. Bean 注册组件:

    SingletonBeanRegister/AliasRegister:将 BeanDefinition 对象注册到 BeanFactory(BeanDefinition Map)中去。注册对象所应用的容器

  5. Bean 形容组件:

    BeanDefinition 体系,Spring 外部对 Bean 形容的根本数据结构。负责形容 BeanDefinition 资源 将资源模式的 bean 转化为 spring 所冀望的格局构造

  6. Bean 结构组件:

    BeanDefinitionReader 体系,读取 Resource 并将其数据转换成一个个 BeanDefinition 对象。负责将一个个的资源 解析转化为 BeanDefinition 为之后形容 bean 做筹备

<img src=”https://tva1.sinaimg.cn/large/007S8ZIlgy1gg9jtxriloj31330mi0w2.jpg” alt=”image-20200205095809050″ style=”zoom:50%;float:left” />

四、BeanFactory

4.1 筹备
  • bean-v1.xml配置 bean 的信息
  • BeanDefinition用于寄存 bean 的定义
  • BeanFactory获取 bean的信息,实例化bean`
  • BeanFactoryTest测试 BeanFactory 是否可用
4.2 代码实现
  1. bean-v1.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
        <bean id="user" class="com.timwang.spring.small.User"/>
        <bean id="invalidBean" class="xxx.xxx"/>
    </beans>    
  2. BeanDefinition

    bean-v1.xml中定义了每个 bean,但这些信息咱们该如何存储呢?spring 是通过 BeanDefinition 接口来形容 bean 的定义

    package com.timwang.spring.small;
    
    /**
     * @author wangjun
*/

public interface BeanDefinition {

   /**
    * 获取 bean.xml 中 bean 的全名 如 "com.niocoder.service.v1.NioCoderService"
    * @return string
    */
   String getBeanClassName();

}


`GenericBeanDefinition` 实现了 `BeanDefinition` 接口

package com.timwang.spring.small;

/**

* @author wangjun
* @date 2020-06-29
*/

public class GenericBeanDefinition implements BeanDefinition {

   private String id;
   private String beanClassName;

   public GenericBeanDefinition(String id, String beanClassName) {
       this.id = id;
       this.beanClassName = beanClassName;
   }

   @Override
   public String getBeanClassName() {return this.beanClassName;}

   public String getId() {return id;}

}


3. BeanFactory

咱们曾经应用 `BeanDefinition` 来形容 `bean-v1.xml` 的 `bean` 的定义, 上面咱们应用 `BeanFactory` 来获取 `bean` 的实例

package com.timwang.spring.small;

/**

* 创立 bean 的实例
* @author wangjun
* @date 2020-06-29
*/

public interface BeanFactory {

   /**
    * 获取 bean 的定义
    * @param beanId beanId
    * @return BeanDefinition
    */
   BeanDefinition getBeanDefinition(String beanId);

   /**
    * 获取 bean 的实例
    * @param beanId beanId
    * @return bean 示例
    */
   Object getBean(String beanId);

}


`DefaultBeanFactory` 实现了 `BeanFactory` 接口

package com.timwang.spring.small;

import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.util.ClassUtils;

import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.dom4j.io.SAXReader;

/**

* BeanFactory 的默认实现类
*
* @author wangjun
* @date 2020-06-29
*/

public class DefaultBeanFactory implements BeanFactory {

   private static final String ID_ATTRIBUTE = "id";
   private static final String CLASS_ATTRIBUTE = "class";
   /**
    * 寄存 BeanDefinition
    */
   private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

   public DefaultBeanFactory(String configFile) {loadBeanDefinition(configFile);
   }

   @Override
   public BeanDefinition getBeanDefinition(String beanId) {return beanDefinitionMap.get(beanId);
   }

   @Override
   public Object getBean(String beanId) {BeanDefinition bd = this.getBeanDefinition(beanId);
       if (bd == null) {throw new BeanCreationException("BeanDefinition does not exist");
       }
       ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
       String beanClassName =  bd.getBeanClassName();
       try {
           // 应用反射创立 bean 的实例,须要对象存在默认的无参构造方法
           Class<?> aClass = classLoader.loadClass(beanClassName);
           return aClass.newInstance();} catch (Exception e) {throw new BeanCreationException("Bean Definition does not exist");
       }
   }

   /**
    * 具体解析 bean.xml 的办法 应用 dom4j
    * @param configFile configFile
    */
   private void loadBeanDefinition(String configFile) {ClassLoader cl = ClassUtils.getDefaultClassLoader();
       try (InputStream is = cl.getResourceAsStream(configFile)) {SAXReader reader = new SAXReader();
           Document doc = reader.read(is);

           Element root = doc.getRootElement();
           Iterator elementIterator = root.elementIterator();
           while (elementIterator.hasNext()) {Element ele = (Element) elementIterator.next();
               String id = ele.attributeValue(ID_ATTRIBUTE);
               String beanClassName = ele.attributeValue(CLASS_ATTRIBUTE);
               BeanDefinition bd = new GenericBeanDefinition(id, beanClassName);
               this.beanDefinitionMap.put(id, bd);
           }
       } catch (Exception e) {throw new BeanDefinitionStoreException("IOException parsing XML document", e);
       }
   }

}


4. BeanFactoryTest

package com.timwang.spring.small;

/**

* @author wangjun
* @date 2020-06-29
*/

public class BeanFactoryTest {

   public static void main(String[] args) {BeanFactoryTest beanFactoryTest = new BeanFactoryTest();
       beanFactoryTest.testGetBean();}

   public void testGetBean() {BeanFactory beanFactory = new DefaultBeanFactory("bean-v1.xml");
       BeanDefinition bd = beanFactory.getBeanDefinition("user");
       String beanClassName = bd.getBeanClassName();
       System.out.println(beanClassName);
   }

}

正文完
 0