JDK動態代理:
1:jdk動態代理是指在運行時動態的創建被代理類的接口的子類。
2:再通過反射調用被代理的類方法。
3:jdk動態代理可以在用戶沒有感覺的情況下,滲入到被代理的方法去執行。(Spring中的AOP思想)
4:只對一個方法不攔截,getClass()
要求:
1:jdk動態代理中所有的被代理的類,都必須要擁有一個接口。沒有接口的類,無法被動態代理。
除了jdk代理還有cglib代理,cglib不需要接口就可以實現動態代理,這兩種在Spring中都可以
以下是一個最基本的JDK動態代理示例:
在JDK中一個類:有兩個核心類:
1:Proxy – 用於在運行時創建被代理類的接口的子類。
2:InvocationHandler – 在執行時攔截被代理類的方法。 執行句柄。
第一步:
/**
* 聲明一個接口
* @author zfx
*/
public interface IPerson {
String run();
}
第二步:
/**
* 被代理類
*/
public class Person implements IPerson {
public String run(){
System.err.println("正在跑步.....");
return "run....";
}
}
第三步:
@Test
public void test2(){
//1:聲明被代理類
final Person p = new Person();
System.err.println("1:聲明被代理類:"+p+",類名是:"+p.getClass());
//2:通過Proxy類的靜態方法,在內存中動態的創建IPerson接口的子類
Object proxyObj = Proxy
.newProxyInstance(TestUserProxy.class.getClassLoader(),
new Class[]{IPerson.class},
new InvocationHandler() {//匿名內部類
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//3:輸出用戶正在調用的方法
System.err
.println("4:正在調用的方法名爲:"+method.getName());
//4:執行目標類的方法,接收返回值
Object returnValue = method.invoke(p,args);
System.err
.println("6:目標方法調用完成,返回值是:"+returnValue);
return returnValue;
}
});
System.err.println("2:創建了被代理類它是:"+proxyObj.getClass());
//5:將proxyobj轉成Iperson接口
IPerson p3 = (IPerson) proxyObj;
System.err.println("3:轉換成功,開始調用");
//6:調用了代理類的run方法
String str = p3.run();
System.err.println("7:調用完成>");
}
Junit執行結果:
1:聲明被代理類:cn.zfx.demo4.proxy.Person@276baafc,類名是:class cn.zfx.demo4.proxy.Person
2:創建了被代理類它是:class com.sun.proxy.$Proxy4
3:轉換成功,開始調用
4:正在調用的方法名爲:run
正在跑步.....
6:目標方法調用完成,返回值是:run....
7:調用完成>