框架前奏
穿插之前的JAVAWEB項目,之後的Spring框架。
JAVAWEB項目:用到技術點
-
MVC模式
-
數據庫連接技術(JDBC)
-
分層思想
1.先創建JAVAWEB項目(IDEA)
使用tomcat,配置運行一下
2.src下的目錄
某新聞系統,主題爲例,Topic
搭建框架
-
com.aaa.dao:數據訪問層的包
-
com.aaa.dao.impl:數據訪問層接口的實現類
-
com.aaa.service:業務層的包,主要放業務層接口
-
com.aaa.service.impl:業務層包的實現類:主要放業務層接口實現類
-
com.aaa.controller:Servlet,去調用業務層的接口及其實現類。
controller是之前的寫法,今天的測試,換成了一個test包,在test包下建立一個test類,來測試業務層接口及其實現類。
這個其實和使用servlet測試是一樣。
剛纔我們講了,搭建。在控制檯做了測試輸出。
3.setter解耦
數據庫mysql,oracle
有mysql的數據訪問層的實現,有oracle的數據訪問層的實現。
業務層,這裏實現的是TopicDaoMysqlImpl,針對的mysql數據庫的操作。
我們現在的操作都變了,要去操作oracle數據庫。怎麼辦呢???
TopicDao topicDao=new TopicDaoMysqlImpl();
代碼改變:
TopicDao topicDao=new TopicDaoOracleImpl();
運行之後,可以看到,會改變爲刪除oracle數據庫中的主題編號:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GKiyCtrG-1591145306194)(E:\政通路\課堂筆記\S2\Spring\assets\image-20200601163742411.png)]y
大家要總結一下,當我們的數據庫變更的時候,這樣操作的方式好不好呢???
假如說,我們的項目已經部署上線了,項目在運行,你來改變代碼來了。不能說肯定會出現問題,但是出現問題的機率一定是比較大。
能不能有一種方式,由客戶自己來決定變更使用哪種數據庫或者是客戶自己決定某種操作。
這種問題,其實就是程序的耦合問題。
之前學習過OOP,三大特徵:封裝、繼承、多態。
要實現的目標是:高內聚、低耦合、高複用
我們在寫程序的時候,儘量低耦合。不new具體的對象;
重點代碼:
package com.aaa.service.impl;
import com.aaa.dao.TopicDao;
import com.aaa.dao.impl.TopicDaoMysqlImpl;
import com.aaa.dao.impl.TopicDaoOracleImpl;
import com.aaa.service.TopicService;
/**
* Created by 張晨光 on 2020/6/1 16:19
* 主題業務層的實現類;java程序員 調用dao層,不改.
* 調用dao層的接口及其實現;
*/
public class TopicServiceImpl implements TopicService {
//定義dao層對象,及其實現類;
//TopicDao topicDao=new TopicDaoMysqlImpl();
//TopicDao topicDao=new TopicDaoOracleImpl();
//這種方式:是通過new 出來dao層對象的具體的實現類。
//能不能有一種方式,交由客戶自己來調用的時候來實現呢???
//儘量少的動代碼;
//這種其實就是程序之間的耦合問題。
//********************松耦合的實現************
TopicDao topicDao;
//創建它的getter/setter
public TopicDao getTopicDao() {
return topicDao;
}
//重點看這個:參數是一個TopicDao的對象;
public void setTopicDao(TopicDao topicDao) {
this.topicDao = topicDao;
}
@Override
public void deleteTopicById(Integer id) {
//在方法裏面,通過dao層對象去執行刪除操作;
//注意看:這裏面有topicDao的對象的new ???沒有了
topicDao.deleteTopicById(id);
}
}
客戶端的使用:
TopicService topicService=new TopicServiceImpl();
//在業務層實現類代碼裏面,已經沒有了new TopicDaoOracleImpl的代碼,我們的目標就是去掉這個
//代碼,實現松耦合
//通過setter來實現
//((TopicServiceImpl) topicService).setTopicDao(new TopicDaoOracleImpl());
//客戶變更爲了mysql
((TopicServiceImpl) topicService).setTopicDao(new TopicDaoMysqlImpl());
//由原來在業務層實現類的具體的new xxxImpl,交由客戶端test類自動選擇,我要new。
//
topicService.deleteTopicById(3);//模擬實現;
總結:
-
耦合度:模塊間的耦合度是指模塊之間的依賴關係;java裏面的耦合度指的是類、接口、實現之間的關聯程度。
-
解耦:通過把創建接口對象的setter()方法,在客戶端由客戶決定哪種數據庫的使用。
-
高內聚:儘可能類的每個成員方法只完成一件事(最大限度的聚合)
-
之前的數據庫連接代碼,放在了BaseDao裏面,是寫死的,需要修改也得改代碼。可以放在db.properties配置文件,也是解耦的一種表現。
作業:
- 使用UserDao來解耦之前JAVAWEB代碼,模仿TopicDao。
—************
首先是熟練操作IDEA,創建WEB項目,使用tomcat,配置、部署運行等。
複習:
面向對象的目標:高內聚、低耦合、高複用
原來JAVAWEB項目存在高耦合的情況,我們要解耦,我們使用的接口對象的setter()方法進行解耦操作。
4.解耦方式二
程序的耦合
耦合:程序間的依賴關係,包括:
a.類之間的關係
b.方法間的關係
解耦:降低程序間的依賴關係
爲bug生,爲bug死,爲bug奮鬥終生
爲解耦生,爲解耦死,爲解耦奮鬥終生–》只要項目你不斷完善,就存在類、方發、模塊、項目之間的耦合度。
實際開發中:
應該做到,編譯時不依賴,運行時依賴
解耦的思路:
第一步:使用反射來創建對象,而避免使用new關鍵字。Class.forName("")
第二步:通過讀取配置文件來獲取要創建的對象全限定類名。xxx.properties/xxx.xml文件
使用xml文件的解耦,這個將來和spring框架會聯繫起來,將我們的技術串起來。以聽爲主,不用記憶。
1.在src下建立beans.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!--beans:指的所有bean的集合,使用xml文件進行解耦-->
<!--bean:單個bean的配置文件;id:bean的編號;class:bean路徑-->
<!--class:mysql下數據庫的實現類;給這個類起id名topicDaoMysqlImpl-->
<bean id="topicDaoMysqlImpl" class="com.aaa.dao.impl.TopicDaoMysqlImpl"></bean>
<!--topicServiceImpl解耦-->
<bean id="topicServiceImpl" class="com.aaa.service.impl.TopicServiceImpl"></bean>
</beans>
bean:咖啡豆;在java 組件
JAVABEAN:指的就是JAVA裏面的可重用組件,玩具:可以由若干零部件組成,組件(組成的零件),在JAVA裏面,業務層的接口、接口的實現類、dao層接口、dao層接口的實現類,可以被多次調用(被重用),這些被重用的類、接口都是JAVABEAN。
JAVABEAN的範圍遠大於實體類,實體類僅僅指的是業務傳遞數據時的一種重用形態。
2.建立BeanFactory類,操作xml文件
2.1 jar包準備
IDEA的web-INF創建,lib目錄,然後把xml的jar放進去,然後Add as Library
2.2 使用BeanFactory來獲取bean
package com.aaa.util;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* Created by 張晨光 on 2020/6/2 15:01
* Bean:重用組件;--》JAVABEAN;
* Factory:工廠的意思;BeanFactory:Bean的工廠;
* 顧名思義:批量創建Bean;操作beans.xml文件,創建bean
*/
public class BeanFactory {
//定義靜態方法根據id來獲取Bean對象;
public static Object getBean(String id){
//用類加載器解析xml文件
try {
SAXReader reader = new SAXReader(); //xml的reader對象
//getClassLoader():類加載器,getResourceAsStream:將資源加載爲流;
Document document = reader.read(BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"));
//xpath技術獲得bean元素;相當於之前js:document.getElementById("id")
Element element = (Element) document.selectSingleNode("//bean[@id='"+id+"']");
//拿到class屬性裏面的值
String value = element.attributeValue("class");
//獲得反射對象
System.out.println(value);
//通過類的全限定名加載類對象[包名+類名];得到value類的class(TopicDaoMysqlImpl):它的類信息;
//是不是可以想到:Class.forName("com.mysql.cj.jdbc.Driver")
Class clazz = Class.forName(value);
//獲得實例
return clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
3.測試類
//2.1通過BeanFactory來獲取一下;
TopicService topicService = (TopicService) BeanFactory.getBean("topicService");
//2.直接調用即可
topicService.deleteTopicById(2);
總結:
1.通過建立配置文件xml解耦
`
3.測試類
//2.1通過BeanFactory來獲取一下;
TopicService topicService = (TopicService) BeanFactory.getBean("topicService");
//2.直接調用即可
topicService.deleteTopicById(2);
總結:
1.通過建立配置文件xml解耦
2.建立BeanFactory解析xml文件,使用反射機制來讀取類信息,創建類實例,實現自動創建對象的操作。