動态代理
靜态代理會為每一個業務增強都提供一個代理類, 由代理類來建立代理對象, 而動态代理并不存在代理類, 代理對象直接由代理生成工具動态生成.
JDK動态代理
- JDK動态代理是使用 java.lang.reflect 包下的代理類來實作. JDK動态代理動态代理必須要有接口.
- JDK動态代理是利用反射機制生成一個實作代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理,需要指定一個類加載器,然後生成的代理對象實作類的接口或類的類型,接着處理額外功能.
- JDK動态代理制能對實作了接口的類生成代理,而不是針對類
//定義兩個dao接口
public interface DeptDao {
public int addDept();
public int updateDept();
}
//實作dao接口中的兩個方法
public class DeptDaoImpl implements DeptDao{
public int addDept() {
System.out.println("添加部門到資料庫中");
return 0;
}
public int updateDept() {
System.out.println("更新部門資訊");
return 0;
}
}
實作代理
//jdk動态代理:代理類實作一個接口
public class DyProxy<T> implements InvocationHandler {
public DyProxy() {
}
public DyProxy(T target) {
this.target = target;
}
//聲明屬性:接收所代理的對象
private T target;
public T getTarget() {
return target;
}
public void setTarget(T target) {
this.target = target;
}
//執行invoke方法就是執行所代理對象的方法
//proxy:所代理的對象
//method:所要執行的方法
//args:要執行方法的參數
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//動态代理對象執行的所代理對象的方法
//聲明變量來存放執行代理對象方法的傳回值
Object o=null;
System.out.println("動态代理開始執行……");
try {
o=method.invoke(target, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
System.out.println("動态代理對象執行方法時發成異常");
} catch (IllegalArgumentException e) {
e.printStackTrace();
System.out.println("動态代理對象執行方法時發成異常");
} catch (InvocationTargetException e) {
e.printStackTrace();
System.out.println("動态代理對象執行方法時發成異常");
} finally {
System.out.println("動态代理執行結束!");
}
return o;
}
}
測試
public class TestProxy {
public static void main(String[] args) {
//建立代理對象
UserDaoProxy userDaoProxy=new UserDaoProxy();
//聲明一個實作類
DeptDaoImpl ddi=new DeptDaoImpl();
//使用代理
InvocationHandler deptProxy=new DyProxy<DeptDaoImpl>(ddi);
DeptDao proxy= (DeptDao) Proxy.newProxyInstance(DeptDao.class.getClassLoader(),
new Class[]{DeptDao.class},
deptProxy);
proxy.addDept();
//還可以給UserDaoImpl做代理
UserDaoImpl udimpl=new UserDaoImpl();
InvocationHandler userProxy=new DyProxy<UserDaoImpl>(udimpl);
//把代理對象 和被代理的綁定在一起
UserDao proxy2=(UserDao)Proxy.newProxyInstance(UserDao.class.getClassLoader(),
new Class[]{UserDao.class},
userProxy);
proxy2.registerUser();
}
}