經典AOP-基於代理

基於代理是一項非常經典的具有AOP思想的實現方法,從這也產生了代理模式。代理其實就是跟委託實現同一個的接口(這是弊端,想要代理就必須有接口),其實現方式有兩種,靜態代理和動態代理。在Java中,安全、日誌、事務都是AOP應用的實際方面。

靜態代理

靜態代理的實現是指通過自己手動的生成一個代理對象,並調用代理對象的方法,靜態代理思想也很好地體現了動態代理的思想精髓。下面是一個日誌的靜態代理。

首先聲明一個接口,這個接口是委託和代理都需要實現的

public interface IDao<T extends Serializable> {

	/**
	 * 將obj保存到數據庫表
	 * @param obj,要保存到數據庫的實體對象
	 */
	public void doSave(T obj);
}

爲了更好地模擬ORM,我們需要定義簡單的實體類

實體類接口

public interface IEntity<T extends Serializable> extends Serializable {

	public T getId();
}

實體類Book

public class Book implements IEntity<Integer>{

	private Integer id;

	public Integer getId() {
		// TODO Auto-generated method stub
		return id;
	}
}

定義委託——BookDao

public class BookDao implements IDao<Book> {

	public void doSave(Book obj) {
		// TODO Auto-generated method stub
		//將對象保存到數據庫表
	}

}

定義代理

public class BookDaoProxy implements IDao<Book> {

	/**
	 * 代理依賴於委託
	 */
	private BookDao dao;
	
	public BookDao getDao() {
		return dao;
	}

	/**
	 * 注入委託
	 * @param dao,需要注入的委託實例
	 */
	public void setDao(BookDao dao) {
		this.dao = dao;
	}

	public void doSave(Book obj) {
		// TODO Auto-generated method stub
		System.out.println("開始記錄日誌");
		dao.doSave(obj);
		System.out.println("結束記錄日誌");
	}

}

這樣子,在實際調用的時候,調用BookDaoProxy類的doSave方法,就不僅能完成委託類的保存實體到數據庫這以功能,還能夠實現日誌記錄功能。

動態代理

動態代理的實現,是要與Java官方提供的接口InvocationHandler相關聯。

這個接口裏面有一個方法:

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		return null;
	}

其中,proxy參數是代理的實例,不要誤當做是委託實例,而method是委託的方法實例,args是方法參數,學過java反射的都知道,通過反射來調用方法method.invoke(對象實例,參數),由於沒有找到委託實例,所以在實現這個接口的時候,我們要在實現類中注入一個委託實例。
public class BookDaoProxy implements InvocationHandler {

	/**
	 * 將要注入的委託實例
	 */
	private Object target;
	
	public Object bind(Object target)
	{
		this.target = target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
	
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("開始記錄日誌");
		Object result = method.invoke(target, args);
		System.out.println("結束記錄日誌");
		return result;
	}

}

bind方法可以根據委託來得到一個代理實例,而接口中的Invoke方法內部的實現還是主要依賴於java的反射。

		BookDao bookDao = new BookDao();
		BookDaoProxy proxy = new BookDaoProxy();
		bookDao = (BookDao) proxy.bind(bookDao);
		bookDao.doSave(new Book());

這樣,就將代理掩飾成爲委託並調用,但實際上執行了代理的doSave方法。



發佈了70 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章