一、静态代理
静态代理的代理类和被代理类有一个相同的接口:
接口:
代码语言:javascript复制public interface HelloInterface {
void sayHello();
void sayNo(String no);
String callYes(int number,String yes);
}
被代理类:
代码语言:javascript复制public class Hello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("Hello zhanghao!");
}
@Override
public void sayNo(String no) {
}
@Override
public String callYes(int number, String yes) {
Log.i("ProxyHandler", "Hello callYes " number " " yes);
return "yes";
}
}
代理类:
代码语言:javascript复制public class HelloProxy implements HelloInterface{
private HelloInterface helloInterface;
public HelloProxy(HelloInterface helloInterface){
this.helloInterface = helloInterface;
}
@Override
public void sayHello() {
System.out.println("Before invoke sayHello" );
helloInterface.sayHello();
System.out.println("After invoke sayHello");
}
@Override
public void sayNo(String no) {
System.out.println("Before invoke sayHello" );
helloInterface.sayNo(no);
System.out.println("After invoke sayHello");
}
@Override
public String callYes(int number, String yes) {
System.out.println("Before invoke sayHello" );
return helloInterface.callYes(number, yes);
}
}
使用静态代理:
代码语言:javascript复制public static void call() {
HelloProxy helloProxy = new HelloProxy(new Hello());
helloProxy.sayHello();
helloProxy.sayNo("no");
helloProxy.callYes(1, "yes");
}
静态代理的优点: 如果是相同接口下的被代理类,可以使用同一个代理类。
静态代理的缺点: 但如果是不同接口的被代理类,则需要再写一个冗长代理类。 另外代理类中需要实现所有被代理类的方法。
二、动态代理
动态代理则弥补了上述静态代理的缺点: 1、如果换不同的接口的被代理类,不用再写一个冗长的代理类,Proxy.newProxyInstance()出来一个代理类就可以。
2、代理类不用实现所有的被代理的方法,一个InvocationHandler 的 invoke() 方法中使用method.invoke(object, args)可以实现。
例如:
代码语言:javascript复制public class ProxyHandler implements InvocationHandler {
private Object object;
public ProxyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String argss = "null";
if(args != null){
argss = args[0].toString();
}
Log.i("ProxyHandler", "Before invoke " object.getClass().getSimpleName()
" " method.getName() " " argss);
method.invoke(object, args);
return null;
}
}
动态代理对上述Hello.java的调用:
代码语言:javascript复制public static void remoteHello() {
HelloInterface hello = new Hello();
HelloInterface helloProxy = (HelloInterface) Proxy.newProxyInstance(
hello.getClass().getClassLoader(), hello.getClass().getInterfaces(),
new ProxyHandler(hello));
helloProxy.sayHello();
helloProxy.sayNo("no");
helloProxy.callYes(1, "s");
}
例如,再代理一个PersonInterface,不用再写代理类:
代码语言:javascript复制public interface PersonInterface {
void getName();
void setColor(String color);
String doString(int number, String yes);
}
被代理类如下Person.java :
代码语言:javascript复制public class Person implements PersonInterface {
@Override
public void getName() {
}
@Override
public void setColor(String color) {
}
@Override
public String doString(int number, String yes) {
Log.i("ProxyHandler", "Person doString " number " " yes);
return null;
}
}
调用时如下所示:
代码语言:javascript复制public static void remotePerson() {
PersonInterface person = new Person();
PersonInterface personProxy = (PersonInterface) Proxy.newProxyInstance(
person.getClass().getClassLoader(), person.getClass().getInterfaces(),
new ProxyHandler(person));
personProxy.getName();
personProxy.setColor("s");
personProxy.doString(1, "d");
}
动态代理的优势: 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。 想想你有100个静态代理类,现在有一个需求,每个代理类都需要新增一个处理逻辑,你需要打开100个代理类在每个代理方法里面新增处理逻辑吗? 有或者代理类有5个方法,每个方法都需要新增一个处理逻辑, 你需要在每个方法都手动新增处理逻辑吗? 想想就挺无趣的。动态代理类帮你一键搞定。
动态代理的缺点: 1、JDK动态代理需要业务实现类所实现的接口。如果业务实现类是没有实现接口而是直接定义业务方法的话,就无法使用JDK动态代理了。(JDK动态代理重要特点是代理接口) 并且,如果业务实现类中新增了接口中没有的方法,这些方法是无法被代理的(因为无法被调用)。动态代理只能对接口产生代理,不能对类产生代理。