我们看
具体代码:
public
void
pro()
throws
Exception{
Tank
t
=
new
Tank ();
InvocationHandler
h
=
new
TimeHandler(
t
);
Moveable
m
= (Moveable)Proxy.newProxyInstance(Moveable.
class
,
h
);
}
这个就是生产代理的代码,上篇看过了。
Moverable 接口:
public
interface
Moveable {
public
void
move();
}
Moverable 接口有一个move方法。
Tank 类:
public
class
Tank
implements
Moveable{
@Override
public
void
move() {
System.
out
.println(
"Tank moving ..."
);
try
{
Thread. sleep(
new
Random().nextInt(10000));
}
catch
(InterruptedException
e
) {
e
.printStackTrace();
}
}
}
这里很简单 就是有一个类叫tank 有个方法叫move可以随机sleep 时间。就是随机暂停一会。
我们现在希望把他通过动态代理,在这个方法前后添加代码,但是不改动原有代码,知道这个方法执行时间。就是知道每次它sleep多少时间。
我们先生成一个Handler 统一代理接口叫 invocationHandler 实现类叫 TimeHandler,就是用于添加时间的Handler。
接口类:
import
java.lang.reflect.Method;
public
interface
InvocationHandler {
public
void
invoke(Object
o
,Method
m
);
}
接口有个invoke方法。
TimeHandler实现类:
import
java.lang.reflect.InvocationTargetException;
import
java.lang.reflect.Method;
public
class
TimeHandler
implements
InvocationHandler {
private
Object
target
;
//构造函数
public
TimeHandler(Object
target
) {
super
();
this
.
target
=
target
;
}
@Override
public
void
invoke(Object
o
, Method
m
) {
long
start
= System. currentTimeMillis();//添加时间记录
System. out.println(
"start time:"
+
start
);
try
{
m
.invoke(
target
);
}
catch
(Exception
e
) {
e
.printStackTrace();
}
long
end
= System. currentTimeMillis();//添加时间记录
System.
out
.println(
"time:"
+ (
end
-
start
));
}
}
上面代码的意思:
这个实现类,实现了一个接口InvocationHandler,并重写了它的invoke方法 这个方法
利用java反射机制将传入的m方法,属于Method类(反射中的Method类),对传进来的这个target对象的方法,添加记录时间的代码。
代码里面调用反射 Method类的invoke方法得到需要的被处理的对象的方法。这个m即传如的未知的方法。
这个例子中,即通过
m
.invoke(
target
);调用tank对象的move方法。后面会调用。
注意说明:
重写的invoke方法和上面的反射函数的invoke不是一个方法。
重写的invoke 方法的第一个参数Object o在这个例子中没有用到。在java源代码里面有用到(先不用管)。
重写的invoke 方法的第二个参数就是Method 的m。
invoke会被循环调用,因为一个实体类中可以有很多方法,这个例子中target是tank,而tank对象下面只有一个move方法。
我们在invoke处理的时候,target就是指定的传递进来的对象。我们回到期初的代码就可以知道。
Tank
t
=
new
Tank ();
InvocationHandler
h
=
new
TimeHandler(
t
);
生成一个Tank 对象,把tank对象传进去。invoke tank这个target对象的m方法。
现在基本的使用的原理就完成了。
Moveable
m
= (Moveable)Proxy.newProxyInstance(Moveable.
class
,
h
);
当我们执行这条语句的时候,newProxyInstance方法 就会通过第一个参数Moveable.class 获得这个Tank对象 override的所有方法名,利用这些方法名会去找第二个参数h (就是TimeHandler)下面调用invoke方法,把这些方法名逐一循环放进invoke方法里面去。这样我们就把tank下面的方法在TimeHandler里面添加了代理。
最后newProxyInstance 帮我们生成对象返回给我们。