1. 程式人生 > >Java——動態代理

Java——動態代理

插入 ref exc tcl try 反射 mil 動態 ()



在靜態代理中,我們在調用target類的時候,都是先拿到proxy類。由於proxy類中將target類作為了成員變量,而且跟target類繼承了一樣的接口,具有同樣的方法,所以,在proxy類中。通過調用target類的方法來對目標類方法的運行前後插入特殊操作。


可是靜態代理有倆缺點:1,代理類特別多,每添加一個target類。就要寫一個代理。2,在proxy類中,可能我們須要插入的操作時同樣的。這就造成了代碼的反復。


所以。通過引入反射,能夠實現動態代理,以對靜態代理進行改進。



/**
 * @ClassName: LogHandler
 * @Description: 用於創建代理類
 * @author 水田
 * @date 2015年12月8日 上午11:17:51
 */
public class LogHandler implements InvocationHandler {
    private Object targetObject;

    public Object newProxyInstance(Object targetObj) {
	this.targetObject = targetObj;
	/*
	 * 1,拿到類的classLoader
	 * 2,得到創建的類的接口
	 * 3,傳入回調invoke方法所在類
	 * */
	return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(),
		targetObj.getClass().getInterfaces(), this);
    }

    /*
     * (非 Javadoc) <p>Title: invoke</p> <p>Description: </p>
     * 
     * @param proxy
     * 
     * @param 調用方法信息
     * 
     * @param args:方法的參數數組
     * 
     * @return
     * 
     * @throws Throwable
     * 
     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
     * java.lang.reflect.Method, java.lang.Object[])
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
	    throws Throwable {
	for (int i = 0; i < args.length; i++) {
	    System.out.println(args[i]);
	}
	try {
	    // 調用目標類的方法,返回一個object,假設方法沒有返回值,則返回null
	    method.invoke(targetObject, args);
	} catch (Exception e) {
	    e.printStackTrace();
	    throw e;
	}

	System.out.println("start----->>>" + method.getName());
	return method.getName();
    }
}

使用演示樣例:


/* 動態代理演示樣例 */
	LogHandler logHandler = new LogHandler();
	UserManager userManager = (UserManager) logHandler
		.newProxyInstance(new UserManagerImpl());
	userManager.addUser("2343254", "lhc");


我們將target類中被調用方法運行前後要插入的操作放在回調函數invoke方法中,當使用代理類調用相應方法的時候。會直接進入invoke方法這裏。使用method,和invoke第三個參數能夠拿到被調用方法的信息。


添加了動態代理之後。明顯去掉了靜態代理的兩個小缺點。技術分享





Java——動態代理