JDK動態代理[1]---靜態代理和動態代理
阿新 • • 發佈:2018-12-19
靜態代理
-
定義介面
public interface Subject {
void visit();
}
-
建立真正實現的類
public class RealSubject implements Subject {
private String name = "proxy.state";
@Override
public void visit() {
System.out.println(name);
}
}
- 建立靜態代理類
public class ProxySubject implements Subject { private Subject subject; public ProxySubject(Subject subject) { this.subject = subject; } @Override public void visit() { subject.visit(); } }
- 使用例子
public class Client {
public static void main(String[] args) {
ProxySubject subject = new ProxySubject(new RealSubject());
subject.visit();
RealSubject realSubject = new RealSubject();
realSubject.visit();
}
}
靜態代理類優缺點
代理類接受一個Subject介面的物件,任何實現該介面的物件,都可以通過代理類進行代理,增加了通用性。 但是也有缺點,每一個代理類都必須實現一遍委託類(也就是realsubject)的介面, 如果介面增加方法,則代理類也必須跟著修改。 其次,代理類每一個介面物件對應一個委託物件, 如果委託物件非常多,則靜態代理類就非常臃腫,難以勝任。
動態代理類
-
定義介面
public interface Subject {
void visit();
}
-
建立真正實現的類
public class RealSubject implements Subject {
private String name = "proxy.dynamic";
@Override
public void visit() {
System.out.println(name);
}
}
- 建立動態代理類
public class DynamicProxy implements InvocationHandler { private Object object; public DynamicProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); before(methodName); Object result = method.invoke(object, args); after(methodName); return result; } /** * 前置通知 * @param method */ public void before(String method){ System.out.println("before the method of "+method); } /** * 後置通知 * @param method */ public void after(String method){ System.out.println("after the method of "+method); } }
- 使用例子
public class Client {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
DynamicProxy proxy = new DynamicProxy(realSubject);
ClassLoader classLoader = realSubject.getClass().getClassLoader();
Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, proxy);
subject.visit();
}
}
動態代理總結
之前我們發現了靜態代理會產生許多重複程式碼,不能很好的進行程式碼複用,而動態代理能夠很好的解決這個問題,代理類TransactionHandler實現了InvocationHandler介面,並且它持有的目標物件型別是Object,因此事務控制代理類TransactionHandler能夠代理任意的物件,為任意的物件新增事務控制的邏輯。因此動態代理才真正的將程式碼中橫向切面的邏輯剝離了出來,起到程式碼複用的目的。但是動態代理也有缺點,一是它的實現比靜態代理更加複雜也不好理解;二是它存在一定的限制,例如它要求需要代理的物件必須實現了某個介面;三是它不夠靈活,動態代理會為介面中的宣告的所有方法新增上相同的代理邏輯。當然,這只是JDK動態代理所存在的一些缺陷,動態代理還有另外的實現如使用CGLIB庫