Servlet22 - BeanFactory

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

posted @   LaViez  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示