由於靜態代理的侷限性,dao層的變動會導致攔截器的變動,由此帶來的一系列框架上的修改,這種缺陷無疑是十分致命的,於是動態代理應運而生。
動態代理通過反射機制實現對dao功能的加載。
應用場景:大量方法需要進行一些公共的操作,比如增刪改查前的日誌記錄、權限驗證等。這些代碼全放在一個方法中完成的話,會有很多重複性的地方,且不易維護。
Spring AOP(面向切面編程)使用的也是這一技術。
示例場景:用戶註冊登錄前進行權限檢查,完成後進行日誌記錄(通過控制檯模擬)
代碼示例:
1. 用戶註冊和登錄的功能接口
package jj.DynamicProxy;
public interface UserDao {
abstract void regist(String user,String pd);
abstract void login();
}
2. 註冊和登錄接口的實現
package jj.DynamicProxy;
public class UserDaoImpl implements UserDao{
@Override
public void regist(String user,String pd) {
System.out.println("正在註冊賬號。。。for " + user);
}
@Override
public void login() {
System.out.println("正在登陸賬號。。。");
}
}
3. 定義攔截器
package jj.DynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("權限檢查。。。");
method.invoke(target, args);
System.out.println("日誌記錄。。。");
return null;
}
}
4.測試類
package jj.DynamicProxy;
import java.lang.reflect.Proxy;
public class TestProxy {
public static void main(String[] args) {
UserDaoImpl ui = new UserDaoImpl();
MyInvocationHandler myHandler = new MyInvocationHandler(ui);
//返回一個指定接口的代理類實例
UserDao dao= (UserDao)Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(), myHandler);
dao.regist("jj","123");
dao.login();
}
}