首页 > 其他分享 >Servlet22 - BeanFactory

Servlet22 - BeanFactory

时间:2023-01-23 16:12:40浏览次数:48  
标签:层内 name BeanFactory 标签 bean 层间 Servlet22 耦合

BeanFactory - IOC - DI

依赖/耦合

  • 软件系统中,层与层间存在依赖关系,称为耦合
  • 设计原则:高内聚低耦合 -- 层内组成代码高度聚集,层间关系低耦合(理想情况-零耦合)

如何实现低耦合? 底层代码的改动不影响上层代码

分层

如何实现修改 FruitService 层,其他层,如 FruitController 层,不用做额外修改?
  • 将所有层在 applicationContext.xml 文件中预先声明,准备好一个 bean 容器存放每个层的信息以及层间关系

    • <beans>
      
          <bean id="fruitDAO" class="com.atguigu.fruit.dao.impl.FruitDAOImpl"/>
          <bean id="fruitService" class="com.atguigu.fruit.service.impl.FruitServiceImpl">
              <!-- property标签用来表示属性;name表示属性名;ref表示引用其他bean的id值-->
              <property name="fruitDAO" ref="fruitDAO"/>
          </bean>
          <bean id="fruit" class="com.atguigu.fruit.controllers.FruitController">
              <property name="fruitService" ref="fruitService"/>
          </bean>
      </beans>
      
    • 层内没有使用其他层方法,单标签,id-class,通过 id 访问 class

    • 层内有调用其他层方法,双标签,标签内添加 property 标签,name-ref,name 是层内使用其他层时,通过 name 调用,ref 表示 name 引用的是哪个层,层内->name->ref->其他层

  • 创建 beanFactory 接口类,通过 ClassPathXmlApplicationContext 类实现,其中实现从 applicationContext.xml 中获取所有 bean 的 id-class 键值对,存放在 beanMap 映射数组中

    • private Map<String,Object> beanMap = new HashMap<>();
      
      public ClassPathXmlApplicationContext(){
          ...
      
      InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
      //1.创建DocumentBuilderFactory
      DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
      //2.创建DocumentBuilder对象
      DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder() ;
      //3.创建Document对象
      Document document = documentBuilder.parse(inputStream);
      
      //4.获取所有的bean节点
      NodeList beanNodeList = document.getElementsByTagName("bean");
      
      for(int i = 0 ; i<beanNodeList.getLength() ; i++){
          Node beanNode = beanNodeList.item(i);
          if(beanNode.getNodeType() == Node.ELEMENT_NODE){
              Element beanElement = (Element)beanNode ;
              String beanId =  beanElement.getAttribute("id");
              String className = beanElement.getAttribute("class");
              Class beanClass = Class.forName(className);
              //创建bean实例
              Object beanObj = beanClass.newInstance() ;
              //将bean实例对象保存到map容器中
              beanMap.put(beanId , beanObj) ;
              //到目前为止,此处需要注意的是,bean和bean之间的依赖关系还没有设置
          }
      }
      
      
    • 保存所有的 bean 节点后,还需要根据层间关系,组装 bean 之间的依赖关系

    • 从 bean 标签中读取子标签 property

    • public ClassPathXmlApplicationContext(){
          ...
      
      for(int i = 0 ; i<beanNodeList.getLength() ; i++){
          Node beanNode = beanNodeList.item(i);
          if(beanNode.getNodeType() == Node.ELEMENT_NODE) {
              Element beanElement = (Element) beanNode;
              String beanId = beanElement.getAttribute("id");
              NodeList beanChildNodeList = beanElement.getChildNodes();
              for (int j = 0; j < beanChildNodeList.getLength() ; j++) {
                  Node beanChildNode = beanChildNodeList.item(j);
                  
                  //如果节点是元素节点且节点名 = property 则读取节点内容
                  if(beanChildNode.getNodeType()==Node.ELEMENT_NODE && "property".equals(beanChildNode.getNodeName())){
                      
                      Element propertyElement = (Element) beanChildNode;
                      String propertyName = propertyElement.getAttribute("name");
                      String propertyRef = propertyElement.getAttribute("ref");
                      
                      //1) 找到propertyRef对应的实例
                      Object refObj = beanMap.get(propertyRef);
                      
                      //2) 将refObj设置到当前bean对应的实例的property属性上去
                      Object beanObj = beanMap.get(beanId);
                      Class beanClazz = beanObj.getClass();
                      Field propertyField = beanClazz.getDeclaredField(propertyName);
                      propertyField.setAccessible(true);
                      propertyField.set(beanObj,refObj);
                  }
              }
          }
      }
      
    • propertyField.set(beanObj,refObj) 中,beanObj 是当前层,refObj 是要访问的其他层,通过反射将 beanObj 的 property 属性添加 refObj

标签:层内,name,BeanFactory,标签,bean,层间,Servlet22,耦合
From: https://www.cnblogs.com/Ashen-/p/17065252.html

相关文章

  • BeanFactory的总结
    BeanFactoryBeanFactory是Spring容器中的一个基本类也是很重要的一个类是Spring容器中的一个基本类也是很重要的一个类,在BeanFactory中可以创建和管理Spring容器中的Bean,它......
  • BeanFactory的总结
    BeanFactoryBeanFactory是Spring容器中的一个基本类也是很重要的一个类是Spring容器中的一个基本类也是很重要的一个类,在BeanFactory中可以创建和管理Spring容器中的Bean,......
  • BeanFactory体系介绍
    BeanFactory体系BeanFactory是Spring最核心的功能,它就是我们常说的SpringIoC容器。BeanFactory体系下包含许多接口,它们分别代表SpringIoC容器的不同功能:BeanFactory......
  • Spring IOC源码(六):IOC容器之 beanFactory后置处理器
    1、源码解析invokeBeanFactoryPostProcessors(beanFactory)调用各种beanFactory处理器,该方法主要实例化所有已经注册的beanFactoryPostProcessor。1.1、BeanFactory......
  • Spring IOC源码(五):IOC容器之 beanFactory准备工作
    1、源码解析prepareBeanFactory(beanFactory)是beanFactory的准备工作,主要是对beanFactory的各种属性做填充。 1//beanFactory的准备工作,配置容器上下文,如容......
  • Spring源码-08-容器refresh之invokeBeanFactoryPostProcessors方法
    Spring源码-08-容器refresh之invokeBeanFactoryPostProcessors方法ConfigurationClassPostProcessor作用的时机扫描注册用户BeanDefinition到Bean工厂一Bean工厂后置处......
  • BeanPostProcessor&BeanFactoryPostProcessor傻傻分不清
    最开始接触spring源码,被一堆的postProcessor搞晕了,翻译也不“包准”,有的翻译为【后置处理器】、有的翻译为【后置增强器】,这里姑且就翻译为处理器吧。众所周知,在spring框架......
  • spring ioc 容器启动过程中 调用的核心方法 - invokeBeanFactoryPostProcessors
    invokeBeanFactoryPostProcessors:调用bean工厂的后置处理器,解析配置类,将配置类注册成Bean定义。调用所有的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProce......
  • beanfactory和factorybean的区别
    BeanFactory是所有Spring Bean的容器根接口,属于IOC容器接口,定义IOC容器管理Bean的规范接口.用于管理Bean(查找Bean以及获取Bean部分元信息) FactoryBean是 一种创建......
  • Spring的IoC容器之BeanFactory
    SpringIoC容器之BeanFactory首先,Spring提供了两种容器类型:BeanFactory和ApplicationContext。BeanFactory:基础容器类型,提供了完整的IoC服务支持。默认采用延迟......