一、在java中怎樣實現動態代理
1、我們要有一個接口,還要有一個接口的實現類,而這個實現類呢就是我們要代理的對象
接口:
1 package org.dynamicproxy.test; 2 3 public interface UserDao { 4 public void addUser(User user); 5 }
接口的實現類(即要代理的對象):
1 package org.dynamicproxy.test; 2 3 public class UserDaoMysqlImpl implements UserDao { 4 5 public void addUser(User user) { 6 // TODO Auto-generated method stub 7 System.out.println("connect to MySQL DataBase..."); 8 System.out.println("id為"+user.getId()+"的用戶信息成功添加到數據庫表中..."); 9 } 10 11 }
順便說下,所謂代理呢也就是在調用實現類的方法時,可以在方法執行前后做額外的工作,這個就是代理。
2、我們要自己寫一個在要代理類的方法執行時,能夠做額外工作的類,而這個類必須繼承InvocationHandler接口
處理類(即能夠做額外工作的類):
1 package org.dynamicproxy.test; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class LogHandler implements InvocationHandler { 7 // 持有被代理對象的引用(此引用可以有外部靈活制定的) 8 private Object target; 9 10 public LogHandler(Object target) { 11 this.target = target; 12 } 13 14 public Object invoke(Object proxy, Method method, Object[] args) 15 throws Throwable { 16 // TODO Auto-generated method stub 17 System.out.println("開始記錄日志,添加用戶方法開始執行..."); 18 method.invoke(target, args); 19 System.out.println("開始記錄日志,添加用戶方法執行結束..."); 20 return null; 21 } 22 23 }
順便說下為什么要繼承InvocationHandler接口呢?
因為代理類的實例在調用實現類的方法的時候,不會調真正的實現類的這個方法, 而是轉而調用這個類的invoke方法(繼承時必須實現的方法),在這個方法中你可以調用真正的實現類的這個方法。
3、用代理類的實例去調用實現類的方法。
1 package org.dynamicproxy.test; 2 3 import java.lang.reflect.Proxy; 4 5 import org.junit.Test; 6 7 public class TestProxy{ 8 9 @Test 10 public void testProxy(){ 11 UserDao userDAO = new UserDaoMysqlImpl(); 12 LogHandler li = new LogHandler(userDAO); //創建一個Handerler對象 13 14 UserDao userDAOProxy = (UserDao)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li); 15 userDAOProxy.addUser(new User("001")); 16 17 } 18 }
newProxyInstance參數含義
* 第一個參數:代理的類加載器,必須和被代理的對象是一個類加載器
* 第二個參數含義:代理對象要實現的那些接口
* 第三個參數:指派方法調用的調用處理程序
代理調用過程
* 得到UserDaoMysqlImpl這個類的一個代理類userDAOProxy,同時為代理類綁定了一個處理類LogHandler li
* 每次調用UserDaoMysqlImpl這個子類的addUser方法時,
* 不是userDAO這個UserDaoMysqlImpl類的實例去調用,
* 而是這個UserDaoMysqlImpl的代理類userDAOProxy去調用它自己的invoke方法,
* 這個invoke方法里呢可以調用userDAO這個實例的addUser方法
所以說要實現java的動態代理,InvocationHandler接口和Proxy是必須要用到的。