1晚碾、JDK的動(dòng)態(tài)代理有一個(gè)接口和一個(gè)類
InvocationHandler接口
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
- 參數(shù)說(shuō)明:
Object proxy:指被代理的對(duì)象
Method method:要調(diào)用的方法
Object[] args:方法調(diào)用時(shí)所需要的參數(shù)
可以將InvocationHandler接口的子類想象成一個(gè)代理的最終操作類赡勘,替換掉$Proxy1紧显。
Proxy類:
Proxy類是專門完成代理的操作類,可以通過(guò)此類為一個(gè)或多個(gè)接口動(dòng)態(tài)地生成實(shí)現(xiàn)類,此類提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{...}
- 參數(shù)說(shuō)明:
ClassLoader loader:類加載器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子類實(shí)例
Ps:類加載器在Proxy類中的newProxyInstance()方法中需要一個(gè)ClassLoader類的實(shí)例指孤,ClassLoader實(shí)際上對(duì)應(yīng)的是類加載器,在Java中主要有一下三種類加載器;
(1)Booststrap ClassLoader:此加載器采用C++編寫,一般開發(fā)中是看不到的恃轩;
(2)Extendsion ClassLoader:用來(lái)進(jìn)行擴(kuò)展類的加載结洼,一般對(duì)應(yīng)的是jre\lib\ext目錄中的類;
(3)AppClassLoader:(默認(rèn))加載classpath指定的類,是最常使用的是一種加載器叉跛。
2.JDK實(shí)現(xiàn)動(dòng)態(tài)代理
與靜態(tài)代理類對(duì)照的是動(dòng)態(tài)代理類松忍,動(dòng)態(tài)代理類的字節(jié)碼在程序運(yùn)行時(shí)由Java反射機(jī)制動(dòng)態(tài)生成,無(wú)需程序員手工編寫它的源代碼筷厘。動(dòng)態(tài)代理類不僅簡(jiǎn)化了編程工作鸣峭,而且提高了軟件系統(tǒng)的可擴(kuò)展性,因?yàn)镴ava 反射機(jī)制可以生成任意類型的動(dòng)態(tài)代理類酥艳。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動(dòng)態(tài)代理類的能力摊溶。
1、RunAble接口
我們想生成RunAble所有實(shí)現(xiàn)類的Proxy充石,先定義接口
package com.mmb.jdk;
public interface RunAble {
public void running();
}
2更扁、定義RunAble的代理類RunAbleProxy
package com.mmb.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class RunAbleProxy implements InvocationHandler {
private Object target;
public Object bind(Object target)
{
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
//取得代理對(duì)象 //要綁定接口(這是一個(gè)缺陷,cglib彌補(bǔ)了這一缺陷)
}
// 重寫invoke方法來(lái)實(shí)現(xiàn)代理方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("$Proxy is ready to run.");
result = method.invoke(target,args);
System.out.println("$Proxy had done.");
return result;
}
}
3赫冬、RunAble接口的實(shí)現(xiàn)類
package com.mmb.jdk;
public class Car implements RunAble {
@Override
public void running() {
System.out.println("Car is running");
}
}
package com.mmb.jdk;
public class Dog implements RunAble {
@Override
public void running() {
System.out.println("Dog is running");
}
}
4浓镜、測(cè)試類ProxyStudy
package com.mmb.jdk;
public class ProxyStudy
{
public static void main(String[] args) {
RunAbleProxy runAbleProxy = new RunAbleProxy();
RunAble runAble = (RunAble)runAbleProxy.bind(new Car());
runAble.running();
System.out.println("=============================================");
RunAble runAble1 = (RunAble)runAbleProxy.bind(new Dog());
runAble1.running();
}}
5、結(jié)果
$Proxy is ready to run.
Car is running
$Proxy had done.
=============================================
$Proxy is ready to run.
Dog is running
$Proxy had done.
但是劲厌,JDK的動(dòng)態(tài)代理依靠接口實(shí)現(xiàn)膛薛,如果有些類并沒有實(shí)現(xiàn)接口,則不能使用JDK代理补鼻,這就要使用cglib動(dòng)態(tài)代理了哄啄。