## Java專題九(2):動態代理
[TOC]
#### JDK靜態代理
> 使用接口代理實現類的方法調用
定義一個接口
~~~
public interface HelloService {
void sayHello();
}
~~~
定義一個實現類
~~~
public class HelloServiceImpl implements HelloService{
@Override
public void sayHello() {
System.out.println("say hello...");
}
}
~~~
測試代理方法
~~~
public class HelloTest {
public static void main(String[] args){
HelloService hello = new HelloServiceImpl();
hello.sayHello();
}
}
~~~
輸出
~~~
say hello...
~~~
#### JDK動態代理
- 可以隱藏委托類
- 在不修改委托類代碼的情況下,可以為委托類的方法增加一些操作,如方法中實際代碼前后增加日志輸出
> 首先通過Proxy為委托類創建代理對象,將代理對象上對方法的調用通過`InvocationHandler`分發給實際的委托類調用,只能為實現了接口的類提供代理。
定義一個接口
~~~
public interface HelloService {
void sayHello();
}
~~~
定義一個委托類,實現接口
~~~
public class HelloServiceImpl implements HelloService{
@Override
public void sayHello() {
System.out.println("say hello...");
}
}
~~~
創建代理類,必須實現`InvocationHandler`接口
~~~
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
~~~
~~~
// java.lang.reflect.Proxy
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h){
// ...
}
~~~
~~~
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class HelloServiceProxy implements InvocationHandler {
private Object target;
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before invoked...");
Object result = method.invoke(target, args);
System.out.println("before invoked...");
return result;
}
}
~~~
測試代理方法
~~~
public class HelloTest {
public static void main(String[] args){
HelloServiceProxy helloServiceProxy = new HelloServiceProxy();
HelloService proxy =
(HelloService) helloServiceProxy.bind(new HelloServiceImpl());
proxy.sayHello();
}
}
~~~
輸出
~~~
before invoked...
say hello...
before invoked...
~~~
#### CGLIB動態代理
HelloServer.java和HelloServiceImpl.java都不用改變,
~~~
public class HelloServiceCglib implements MethodInterceptor {
private Object target;
public Object getInstance(Object target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperClass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.setCallback(this);
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy porxy)
throws Throwable {
System.out.println("before invoked...");
Object returnObj = porxy.invokeSuper(obj, args);
System.out.println("before invoked...");
return returnObj ;
}
}
~~~
- JavaCook
- Java專題零:類的繼承
- Java專題一:數據類型
- Java專題二:相等與比較
- Java專題三:集合
- Java專題四:異常
- Java專題五:遍歷與迭代
- Java專題六:運算符
- Java專題七:正則表達式
- Java專題八:泛型
- Java專題九:反射
- Java專題九(1):反射
- Java專題九(2):動態代理
- Java專題十:日期與時間
- Java專題十一:IO與NIO
- Java專題十一(1):IO
- Java專題十一(2):NIO
- Java專題十二:網絡
- Java專題十三:并發編程
- Java專題十三(1):線程與線程池
- Java專題十三(2):線程安全與同步
- Java專題十三(3):內存模型、volatile、ThreadLocal
- Java專題十四:JDBC
- Java專題十五:日志
- Java專題十六:定時任務
- Java專題十七:JavaMail
- Java專題十八:注解
- Java專題十九:淺拷貝與深拷貝
- Java專題二十:設計模式
- Java專題二十一:序列化與反序列化
- 附加專題一:MySQL
- MySQL專題零:簡介
- MySQL專題一:安裝與連接
- MySQL專題二:DDL與DML語法
- MySQL專題三:工作原理
- MySQL專題四:InnoDB存儲引擎
- MySQL專題五:sql優化
- MySQL專題六:數據類型
- 附加專題二:Mybatis
- Mybatis專題零:簡介
- Mybatis專題一:配置文件
- Mybatis專題二:映射文件
- Mybatis專題三:動態SQL
- Mybatis專題四:源碼解析
- 附加專題三:Web編程
- Web專題零:HTTP協議
- Web專題一:Servlet
- Web專題二:Cookie與Session
- 附加專題四:Redis
- Redis專題一:數據類型
- Redis專題二:事務
- Redis專題三:key的過期
- Redis專題四:消息隊列
- Redis專題五:持久化