使用Java内置的动态代理模式
一、什么是动态代理
利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。即动态的生成静态代理
二、先讲讲静态代理
假设现在我们有一个Animal接口和其一个实现类Cat,代码如下 Animal:
public interface Animal {
void eat();
void run();
}
Cat:
public class Cat implements Animal {
@Override
public void eat() {
System.out.println( "吃鱼" );
}
@Override
public void run() {
System.out.println( "猫步" );
}
}
现在有一个要求,规定在不修改Animal和Cat的代码的情况下,仅将Cat的eat函数的输出改为“吃屎”。 这里你可以使用静态代理模式,实现起来也比较简单,代码如下:
public class CatProxy implements Animal {
Cat obj=null;
CatProxy(Cat obj){
this.obj = obj;
}
@Override
public void eat() {
System.out.println( "吃屎" );
}
@Override
public void run() {
obj.run();
}
}
但是静态代理有一个缺点,就是当Cat类中的函数很多时,假设有100个,我只想修改其中1个,就仍需要在CatProxy中调用其他99个不会被修改的函数。而且当修改Animal接口时,不仅要修改Cat类,还需要修改CatProxy类。如此看来,静态代理虽然简单,但一旦遇到稍微复杂的地方,就变得十分冗余繁琐,不易维护。
三、如何使用Java提供的动态代理模式
还是Animal接口和Cat类:
Animal:
public interface Animal {
void eat();
void run();
}
Cat:
public class Cat implements Animal {
@Override
public void eat() {
System.out.println( "吃鱼" );
}
@Override
public void run() {
System.out.println( "猫步" );
}
}
接下来使用Java提供的动态代理,新建一个CatInvoc类,并实现InvocationHandler接口,代码如下:
public class CatInvoc implements InvocationHandler {
private Animal obj;
public CatInvoc(Animal obj) {
this.obj = obj;
}
/**
* @param proxy 不怎么用
* @param method 函数对象
* @param args 参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = null;
return invoke;
}
}
还是刚刚那个需求,仅将Cat的eat函数的输出改为“吃屎”,代码如下:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = null;
if ("eat".equals( method.getName() )) {
System.out.println( "吃屎" );
} else {
invoke = method.invoke( obj, args );
}
return invoke;
}
这里通过method.getName()获取函数名,当函数名为eat时,执行System.out.println( "吃屎" )。其他情况时则执行invoke = method.invoke( obj, args ),正常执行被代理对象的函数。 接下来新建一个CatProxy类,代码如下:
import java.lang.reflect.Proxy;
public class CatProxy {
Animal getAnimal(Animal animal) {
return (Animal) Proxy.newProxyInstance(
animal.getClass().getClassLoader(),
animal.getClass().getInterfaces(),
new CatInvoc( animal ) );
}
}
getAnimal()用于返回一个代理对象。Proxy.newProxyInstance(类加载器,接口,invoc对象)通过反射创建出一个代理对象,不难看出动态代理的本质就是动态的生成静态代理。
Loading...