Java代理
在代理之前,我们需要知道我们代理的东西是什么
比如说我们有一个原对象,我们不直接去访问他,我们通过代理去访问它,这么做的目的是,以后不用修改原对象,可以通过修改代理类,来实现具体的方法,来看具体例子:
首先要有一个接口
public interface IUser {
void show();
void create();
void update();
}
接着实现一下
public class Userimpl implements IUser {
public Userimpl(){}
public void show(){
System.out.println("展示");
}
public void create(){
System.out.println("新建");
}
public void update(){
System.out.println("更新");
}
}
再来一个代理
public class UserProxy implements IUser{
IUser user;
public UserProxy(){}
public UserProxy(IUser user){ this.user = user; }
@Override
public void show() {
user.show();
System.out.println("调用了show");
}
public void create(){
user.create();
System.out.println("调用了新建");
}
public void update(){
user.update();
System.out.println("调用了更新");
}
}
然后我们就可以用了
public class ProxyTest {
public static void main(String[] args) {
IUser user = new Userimpl();
IUser userProxy = new UserProxy(user);
userProxy.show();
输出:
展示
调用了show
此处这个代理方法与调用本身没有什么关系,可以当成一个记录日志的行为,但是这个行为本身和我调用show方法没什么联系,但是这个日志又必须要有,但是问题就来了,如果我们要代理的东西太多,怎么办??总不能先上面我写的一样,一个方法一个日志记录格式吧,于是java官方便出了另一种代理方式,叫动态代理
这个动态代理我们可以假设一下的工作机制,无非就是为了方便点来做到调用
public class UserProxy implements IUser{
IUser user;
public UserProxy(){}
public UserProxy(IUser user){ this.user = user; }
IUser user = new Userimpl();
Class c = user.getClass();
Method usermethod = c.getMethod("show");
public void execute(){
System.out.println("调用了" + usermethod.getName());
usermethod.invoke(user,args)
}
}
(上述代码我直接在md敲的,没有导入包)
但是我们发现还有一个问题就方法获取的一个问题,依然冗杂了,如果我们要的不是show,那么就要替换show,或者再来一个反射,但是不巧的是,java官方针对获取方法冗杂这个问题,来了一个很好的解决办法,也就是动态代理,来看一下
java.lang.reflect.Proxy
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
它的前两个参数都可以有固定写法,比较好解决
Proxy.newProxyInstance(user.getClass().getClassLoader(),
user.getClass().getInterfaces(),
userinvocationhandler);
但是最后一个处理器参数,我们需要关心一下
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class UserInvocationHandler implements InvocationHandler {
IUser user;
public UserInvocationHandler(){}
public UserInvocationHandler(IUser user){
this.user = user;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用了" + method.getName());
method.invoke(user,args);
return null;
}
}
这样的话main方法就是这样
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
IUser user = new Userimpl();
InvocationHandler userinvocationhandler = new UserInvocationHandler(user);
IUser userproxyInstance = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(),
new Class[]{IUser.class},
userinvocationhandler);
userproxyInstance.update();
}
}
而我们所选择的method的传递方式就可以是userproxyInstance.方法名了,用起来比较方便
|