天天看點

java web 項目實作 耦合-解耦 解決方案----工廠模式入門級别

1.主要思想就是使用工廠設計模式,将service層和dao層進行解耦

    控制反轉就是(inversion of control)将控制權交個自定的一個工廠來實作,我們要做的就是,通過自定義beanfactory 得到需要的serviceiml 和 daoiml對應的類

說白了,不用serviceiml依賴dao層

這裡使用ServletContextListener 監聽器來讓tomcat啟動時,加載配置檔案,

     這裡就按照我自己的了解來說明,最近幾天研究的結果,當然有老師指導的結果-----------黑馬31期

java web 項目實作 耦合-解耦 解決方案----工廠模式入門級别
java web 項目實作 耦合-解耦 解決方案----工廠模式入門級别

   1,進行監聽器的實作

      目的:可以第一時間加載配置檔案

  2. 配置檔案中注冊監聽器

<!-- 注冊Context監聽器 -->
         <listener>


         <listener-class>com.itheima.ebs.web.Listener.ApplicationContextListener</listener-class>


         </listener>      

  3,當監聽器在tomcat啟動時加載配置檔案。配置檔案名:applicationContext.xml (預設)

public class ApplicationContextListener implements ServletContextListener {

         @Override
         public void contextInitialized(ServletContextEvent sce) {

          // 0 獲得servletContext對象應用
          ServletContext context = sce.getServletContext();
          // 0.1加載配置
          String config = context.getInitParameter("config");

          if (config != null) {
           // 1.1 處理路徑不同情況(我們都知道,配置檔案,
           //可以放在src下面,可以放在web-inf下)
           String[] arr = config.split(":");
           //使用流的方式進行讀取
           InputStream xmls = null;
           try {
           //如果放在classpath:applicationContext.xml
            if (arr.length == 2) {

             // 使用類加載器來加載配置檔案
             xmls = ApplicationContextListener.class.getClassLoader()
               .getResourceAsStream(arr[1]);
            // 如果在WEB-INF下面
            } else if (arr.length == 1) {
            //使用servletContext的方法來加載
             xmls = context.getResourceAsStream(config); // 放到WEB-INF下
            }
           } catch (Exception e) {
            throw new RuntimeException("資源檔案加載不成功" + config);
           }
           // 如果不等于Null,加載到了配置檔案
           if (xmls != null) {
            // 2使用dom4j進行解析,為了友善查找,我們選在了map容器進行存儲
            //定義了xmlUtil工具類,友善代碼的維護--傳回map集合
            Map<String, Bean> data = XmlUtil.parserBeanXml(xmls);
            //3 将解析結果放置到工廠中
            BeanFactory.setBeanData(data);
           }
          }
         }

           4.  我們使用dom4j進行解析:
             <beans>

                <bean name="CategoryDao" class="com.itheima.ebs.dao.impl.CategoryDaoImpl">

                </bean>

                <bean name="UserDao" class="com.itheima.ebs.dao.impl.UserDaoiml">

                </bean>
           
              </beans>


            public class XmlUtil {

            public static Map<String, Bean> parserBeanXml(InputStream xml) {

              try {
                   //定義一個容器
                  Map<String, Bean> data = new HashMap<String, Bean>();

                // 1解析檔案,并獲得Document對象
                SAXReader reader = new SAXReader();
                // 2.擷取docuemnt
                Document document = reader.read(xml);
                // 3 得到 beans
                Element root = document.getRootElement();
                // 獲得bean 元素集合
                List<Element> allBeanElements = root.elements();
                // 周遊取值(name:value  class:value)
                for (Element elements : allBeanElements) {

                  String beanName = elements.attributeValue("name");
                  String beanClass = elements.attributeValue("class");
                  // 為了後期友善對xml、
                  檔案中配置擴充使用面向對象封裝的思想将bean對象封裝到特殊的 bean中
                  Bean bean = new Bean(beanName, beanClass);

                  data.put(beanName, bean);
                }
                //封裝好的bean進行傳回
                return data;
               
              } catch (Exception e) {
                throw new RuntimeException(e);
              }

            }

          5 .bean對象的封裝

            package com.itheima.ebs.Factory;

          public class Bean {

           
            private String beanName;
            private String beanClass;
           
            public Bean() { }
           
            public Bean(String beanName, String beanClass) {
           
              this.beanName = beanName;
              this.beanClass = beanClass;
            }

              ---《 setter/getter方法 》----
           
          }

+++++++++++++++++++++++++++++++++++++++++++++++++++++
BeanFactory:

 beanfactory要提供一個自動生對應的bean對象,保證對象的唯一
  這裡使用單例模式,加上反射思想,通過。class。fornam("類的全限定名").newInstance()

 

package com.itheima.ebs.Factory;

import java.util.Map;

/**
 *
 * 執行個體工廠-單例模式
 *
 * @return
 */
public class BeanFactory {

  private static BeanFactory factory = new BeanFactory();
  //存取bean的 key--value 的一個map對象
  private static Map<String, Bean> beanData;
  //bean 資料緩存集合
  private BeanFactory() {}
  public static BeanFactory getInstance() {
    return factory;
  }
  //向外部提供一個getbean的方法
  //因為是工廠類,是以不依賴任何外部類,使用object作為傳回類型
  public Object getBean(String beanName) {
    try {
      //通過bean的名稱--value(map.get(key)-----value)
      Bean bean=beanData.get(beanName);

      String beanclass=bean.getBeanClass();
      //初始化一個對象進行傳回
      return Class.forName(beanclass).newInstance();
    } catch (Exception e) {
          throw new RuntimeException(e);
    }

  }
  public static void setBeanData(Map<String, Bean> beanData) {
    //從配置檔案中讀取bean資訊傳入工廠,從工廠往外取
    //使用提供一個set方法來共外界,将解析過的map容器,set到工廠中

    BeanFactory.beanData=beanData;
  }

}      

這樣一個簡單的解耦,就可以實作了,我們就可以通過配置檔案,來指定sevice層--serviceimpl

serviceimpl層和dao層,--dao層和daoimpl的解耦。互相不進行依賴。

繼續閱讀