Spring框架學習與實踐(八)

Spring JDK動態代理演練

JDK 動態代理是通過 JDK 中的 java.lang.reflect.Proxy 類實現的。下面通過具體的案例演示 JDK 動態代理的使用。

1. 創建項目

在 Eclipse 中創建一個名稱爲 springDemo03 的 Web 項目,將 Spring 支持和依賴的 JAR 包複製到 Web 項目的 WEB-INF/lib 目錄中,併發布到類路徑下

2. 創建接口 CustomerDao

在項目的 src 目錄下創建一個名爲 com.mengma.dao 的包,在該包下創建一個 CustomerDao 接口,編輯後如下所示:

package com.mengma.dao;

public interface CustomerDao {
	public void add(); // 添加
	
	public void update(); // 修改
	
	public void delete(); // 刪除
	
	public void find(); // 查詢

}

3. 創建實現類 CustomerDaoImpl

在 com.mengma.dao 包下創建 CustomerDao 接口的實現類 CustomerDaoImpl,並實現該接口中的所有方法,如下所示:

package com.mengma.dao;

public class CustomerDaoImpl implements CustomerDao {

	@Override
	public void add() {
		// TODO Auto-generated method stub
		System.out.println("添加客戶...");
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		System.out.println("修改客戶...");
	}

	@Override
	public void delete() {
		// TODO Auto-generated method stub
		System.out.println("刪除客戶...");
	}

	@Override
	public void find() {
		// TODO Auto-generated method stub
		System.out.println("查找客戶...");
	}

}

4. 創建切面類 MyAspect

在 src 目錄下,創建一個名爲 com.mengma.jdk 的包,在該包下創建一個切面類 MyAspect,編輯後如下所示:

package com.mengma.jdk;

public class MyAspect {
	public void myBefore() {
		System.out.println("方法執行之前");
	}
	
	public void myAfter() {
		System.out.println("方法執行之後");
	}

}

上述代碼中,在切面中定義了兩個增強的方法,分別爲 myBefore() 方法和 myAfter() 方法,用於對目標類(CustomerDaoImpl)進行增強

5. 創建代理類 MyBeanFactory

在 com.mengma.jdk 包下創建一個名爲 MyBeanFactory 的類,在該類中使用 java.lang.reflect.Proxy 實現 JDK 動態代理,如下所示:

package com.mengma.jdk;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.mengma.dao.CustomerDao;
import com.mengma.dao.CustomerDaoImpl;

public class MyBeanFactory {
	public static CustomerDao getBean() {
		// 準備目標類
		final CustomerDao customerDao = new CustomerDaoImpl();
		// 創建切面實例類
		final MyAspect myAspect = new MyAspect();
		// 使用代理類,進行增強
		return (CustomerDao) Proxy.newProxyInstance(
				MyBeanFactory.class.getClassLoader(),
				new Class[] { CustomerDao.class },
				new InvocationHandler(){
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						myAspect.myBefore(); // 前增強
						Object obj = method.invoke(customerDao, args);
						myAspect.myAfter(); // 後增強
						return obj;
					}
				});
	}

}

上述代碼中,定義了一個靜態的 getBean() 方法,這裏模擬 Spring 框架的 IoC 思想,通過調用 getBean() 方法創建實例,第 14 行代碼創建了 customerDao 實例。
第 16 行代碼創建的切面類實例用於調用切面類中相應的方法;第 18~26 行就是使用代理類對創建的實例 customerDao 中的方法進行增強的代碼,其中 Proxy 的 newProxyInstance() 方法的第一個參數是當前類的類加載器,第二參數是所創建實例的實現類的接口,第三個參數就是需要增強的方法。

在目標類方法執行的前後,分別執行切面類中的 myBefore() 方法和 myAfter() 方法。

6. 創建測試類 JDKProxyTest

在 com.mengma.jdk 包下創建一個名爲 JDKProxyTest 的測試類,如下所示:

package com.mengma.jdk;

import org.junit.Test;

import com.mengma.dao.CustomerDao;

public class JDKProxyTest {
	@Test
	public void test() {
		// 從工廠獲得指定的內容(相當於Spring獲得,但此內容是代理對象)
		CustomerDao customerDao = MyBeanFactory.getBean();
		// 執行方法
		customerDao.add();
		customerDao.update();
		customerDao.delete();
		customerDao.find();
	}

}

上述代碼中,在調用 getBean() 方法時,獲取的是 CustomerDao 類的代理對象,然後調用了該對象中的方法。

7. 運行項目並查看結果

使用 JUnit 測試運行 JDKProxyTest,運行成功後,控制檯的輸出結果如圖:

從輸出結果中可以看出,在調用目標類的方法前後,成功調用了增強的代碼,由此說明,JDK 動態代理已經實現。

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