學習Spring之動態代理

最近上班工作不是很忙,就補了一下基礎知識,在傳智播客上找了一些免費的視頻,下載下來慢慢看,爲了讓自己很好的吸收,還是要多動手實踐啊

在講動態代理之前先做一個很好理解的靜態代理的小例子:

說到代理,很容易想到的就是中介,例如房屋中介,不僅代替房東(房東本人也可以講房屋出租給客戶)將房屋出租給客戶(基本業務接口),還收取了中介費,轉化爲代碼

房租出租業務接口:

public interface RentInterface {
	public void rent();
}
房東實現房屋出租:

public class Host implements RentInterface{
	
	public void rent() {
		System.out.println("房屋出租");		
	}

}
中介實現房屋出租:

public class HouseProxy implements RentInterface {
	private Host host;
	public void setHost(Host host) {
		this.host = host;
	}
	//構造方法
	public HouseProxy(Host host) {
		super();
		this.host = host;
	}

	@Override
	public void rent() {
		//不僅實現了房屋出租還收取了中介費
		host.rent();
		System.out.println("收取中介費");
	}

}
客戶從代理那裏租房:

public class client {
	public static void main(String[] args) {
		System.out.println("客戶來了");
		Host host=new Host();
		HouseProxy houseProxy=new HouseProxy(host);
		houseProxy.rent();
	}
}
運行結果:


可以看到使用靜態代理的明顯優點是不僅可以實現原來的業務接口,還能添加些屬於自己的的業務,使得原來的業務接口更加純粹

缺點:一個業務接口需要一個代理實現類,增加開發代碼量

接着便是靜態代理的升級版——動態代理

主要有兩種實現方式:

1、基於接口的動態代理——jdk動態代理

2、基於類的動態代理——cglib

這裏主要講jdk動態代理

先看下API文檔說明(其實我看了也真的不理解)


則之前的靜態代理代碼中只需要改動:

public class HouseProxy implements InvocationHandler {
	private Object target;

	public void setTarget(Object target) {
		this.target = target;
	}
	public Object getProxy() {
		/**
		 * 返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序。
		 * newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
		 *@param     loader定義代理類的類加載器 
		 *@param 	 interfaces - 代理類要實現的接口列表 
		 *@param   	 h - 指派方法調用的調用處理程序 
		 * */
		return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		log(method.getName());
		Object result = method.invoke(target, args);
		return result;
	}
	public void log(String methodName){
		System.out.println("調用了"+methodName+"方法");
	}

}

public class client {
	public static void main(String[] args) {
		System.out.println("客戶來了");
		/*Host host=new Host();
		HouseProxy houseProxy=new HouseProxy(host);
		houseProxy.rent();*/
		Host host=new Host();
		HouseProxy proxy = new HouseProxy();
		proxy.setTarget(host);
		RentInterface host2=(RentInterface)proxy.getProxy();
		host2.rent();
		
	}
}
爲了更好的理解,我們再引入一個業務接口賣東西:

public interface SellInterface {
	public void sell();
}

超市實現商品銷售:

public class Market implements SellInterface{
	
	public void sell() {
		System.out.println("賣商品");
		
	}

}
客戶即可以通過代理實現房屋出租,也可以買東西
public class client {
	public static void main(String[] args) {
		System.out.println("客戶來了");
		/*Host host=new Host();
		HouseProxy houseProxy=new HouseProxy(host);
		houseProxy.rent();*/
		Host host=new Host();
		HouseProxy proxy = new HouseProxy();
		proxy.setTarget(host);
		RentInterface host2=(RentInterface)proxy.getProxy();
		host2.rent();
		Market market = new Market();
		proxy.setTarget(market);
		SellInterface sellInterface=(SellInterface)proxy.getProxy();
		sellInterface.sell();
	}
}


不難發現,相比於靜態代理,動態代理大大實現了代碼簡化及高效利用,無論有多少個業務接口,只要一個動態代理實例都能進行實現

動態代理其實它的編碼思想是一種代理模式,對於項目來說,公共的必不可少單獨實現又繁瑣的業務都可以利用動態代理來實現,如日誌、事物、緩存、安全權限、異常處理……



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