學習Spring筆記二

動態代理模式

靜態代理:代碼複用不高,將來維護時難

動態代理:靜態代理上提供的,因爲代理比較常用,JDK提供了一套生成代理類的方式proxy類(遇到什麼問題先看JDK有沒有提供解決方法),動態代理的特點是把增強的功能包裝成一個類,這個類要實現InvocationHandler接口,看到InvocationHandler要條件反射想到動態代理。代理類實現增強功能的類都需要委託類做屬性,因爲需要它們來做參數,寫到有參構造裏。不論靜態、動態都需要!



實例代碼

1.dao.impl下建立UserDaoFactory類

public class UserDaoFactory{

UserDao userDao= new UserDaoImplForMysql();    //這個委託類,作爲回調函數的參數。學習框架後,這樣把類作爲屬性,傳值的方式越常見

public static UserDao getInstance(){

UserDao proxy =(UserDao)Proxy.newProxyInstance(

UserDao.class.getClassLoader(),     //獲得字節碼

UserDaoImplForMysql.class.getInterfaces(),     //代理類和委託類實現同一接口(相似性),這裏是獲取代理類、委託類的接口

new LogHandler(userDao)  //LogHandler類是代理類,userDao是委託類,在這裏把他們動態組合成一個代理,所以這是動態代理的重點(這兩個類需要分別實現)

);

return proxy;

}

public static void main(String[ ]  args){

UserDao dao = UserDaoFactory.getInstance();    //UserDaoFactory是不用new的,因爲getInstance方法是static的,只需要通過UserDaoFactory來引用即可,不用new

dao.add();

}

}




2.建立一個handler包,裏面有一個LogHandler類,內容如下

public class LogHandler implements InvocationHandler{    //實現InvocationHandler接口,這是個動態代理類

public Object obj;       //委託類對象的引用


public LogHandler(Object obj){     //有參構造 ,爲了嵌套委託類而寫

super();

this.obj = obj;

}


public Object invoke(Object proxy,Method method,Object[ ]  args)throws Throwable {   //實現InvocationHandler接口會實現invoke方法

System.out.println("系統日誌!!!");

method.invoke(obj,args);       //這裏的invoke方法可以這樣理解,客戶類action調用UserDaoFactory的getInstance方法,這個方法的Proxy.newProxyInstance裏的第三個參數去調用此invoke方法,然後這個方法返回給Proxy.newProxyInstance,再返回給getInstance,再一層層向上返回。先一層層向下調用 ,然後按順序再返回。

return null;

}

}




3.另外還需要接口UserDao,UserDaoImplForMysql,和其它實例中的一樣。實例結束,可以運行main方法測試


解釋一下動態代理

動態代理是通過proxy對象把委託類(UserDaoImplForMysql) 和代理類(LogHandler) 組合了起來!!

action調用的是Factory中的proxy對象的newProxyInstance方法,它裏面的回調函數調用代理類來執行作爲參數的委託類“new LogHandler(userDao)”  userDao委託類的接口,LogHandler代理類。(回調函數要好好練一練)

動態代理默認會景程委託類的所有方法,如果你在UserDao接口裏添加del方法,並且它的實現類也實現了該方法,在main方法添加dao.del();執行時會也在del外增強LogHandler的功能。



動態代理的proxy對象的詳細解說

共3個參數,第一個classloader,第二個是獲取接口(可以對這個接口下的實現類造成影響),第三個是回調函數,它的參數是委託類。在當前類顯示的是userDao,在LogHandler類裏是obj引用。$ProxyN 是jdk製作出來的代理類的命名規則。看到控制檯打印這種形式的應該知道這是JDK的代理類。


代理類兩個原則:相似性和增強

動態代理:委託類必須有接口,代理類才能和委託類相似。因爲接口就是對於這個類的描述。就像一張圖紙定義這個類的。缺點是必須和有接口。



只要是遠程方法之間調用,不同語言之間溝通,兩臺機器之間溝通。這些東西全都是代理。所以代理模式非常重要,它是一個思維的基礎,沒有這個思維的基礎,腦海裏面就建立不起來這個模型。



————————動態代理   end ——————————————————





Spring正題——————

什麼項目適合用Spring?

中型最合適,大型分佈式項目用EJB

Spring+webservice也可以實現分佈式項目(分佈式項目是指,一個子系統在北京,另一個子系統在海南這樣的項目)



Spring的helloworld代碼start——————

1.下載jar包(jar包中docs/MVC-step-by-step是教SpringMVC的)

它的lib包下有好多其它的框架的包,因爲Spring可以和它們整合,Spring自己的jar包則放在了dist文件夾下面(一般下載下來的jar包,核心文件常會放在dist文件夾下)

spring.jar包需要拷貝,modules文件夾下面的jar包是把spring.jar包分解開的小jar包,你可以看情況選擇用哪個。

spring-sources.jar也一起拷貝到項目中。


a)  把spring.jar和spring-sources.jar拷貝到項目下

b)  把jarkarta-commons的commons-logging.jar拷貝到項目下



2.src下建立beans.xml,它的內容沒必要記,要拷貝,自己寫容易寫錯

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">


<bean id="userDao" class="com.bjsxt.dao.UserDao"  lazy-init="true"></bean> //這個bean要對應到項目中,要寫個userDao類,默認是餓加載,要寫lazy-init="true"變成懶加載

</beans>




3.建立dao包,包下建立UserDao類

public class UserDao{

public UserDao(){

System.out.println("init......");

}

public void add (){

System.out.println("Hello Spring");

}

}



4.建立test包,包下建立Test類,來創建spring提供的IOC容器,當然,不是我們自己手寫,和代理一樣,JDK有提供相關API(JAVA這麼規範、強大的語言,很多都提供了接口,其實很簡單)

public class Test{

//IOC像一個大工廠,單例、工廠、代理、IOC模式它都包括

public static void main(String[ ] args){

ApplicationContext ac = new ClassPathXmlApplicationContext(

new String[ ] {"beans.xml"} //AC容器在讀取beans.xml配置文件

);

UserDao userDao = (UserDao)  ac.getBean("userDao");     //AC容器從beans.xml中找到userDao,通過反射實例化UserDao,然後使用它的方法。通過IOC容器來統一實例化,達到控制對象與對象之間的關係,而不是你想實例化誰就實例化誰。

userDao.add();

}

}


Spring的helloword  end——————————


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章