代理是基本的设计模式之一,说一说它的一个定义:它是你为了提供额外的不同操作,而插入的用来代替“实际”对象的的对象。
首先面向接口编程是我们代理的开始,接口一般我们用来做方法回调,和搭架子用。
public interface Interface {
void doSomthing();
void doSomethingElse(Object proxied);
}
再写一个实体类来实现它做点事
public class RealObject implements Interface {
@Override
public void doSomthing() {
System.out.println("doSomething");
}
@Override
public void doSomethingElse(Object proxied) {
System.out.println("doSomethingElse"+proxied);
}
}
现在写个main方法来用一用最简单的代理
public class SimpleProxyDemo {
public static void main(String[] args) {
consumer(new RealObject());
consumer(new SimpleProxy(new RealObject()));
}
public static void consumer(Interface iface){
iface.doSomthing();
iface.doSomethingElse(" lala");
}
}
我们运行的结果:
doSomething
doSomethingElse lala
SimpleProxy doSomeThing
doSomething
SimpleProxy doSomethingElse
doSomethingElse lala
这就是代理,在任何时刻,只要你想要将额外的操作从“实际”对象中分离到不同的地方,特别是当你希望能够很容易地做出修改,从没有使用额外操作转为使用这些操作,或者反过来时。
Java的动态代理:可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。
public class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public static int number = 0;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
number++;
System.out.println("***proxy"+proxy.getClass()+",method:"+method+",args"+args+"number"+number);
if (args!=null)
for (Object arg : args) {
System.out.println(" "+arg);
}
return method.invoke(proxied,args);
}
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
}
然后我们写个main方法试试效果
public class SimpleDynamicProxy {
public static void main(String[] args) {
RealObject realObject = new RealObject();
consumer(realObject);
Interface anInterface = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(),
new Class[]{Interface.class},
new DynamicProxyHandler(realObject));
consumer(anInterface);
}
public static void consumer(Interface iface){
iface.doSomthing();
iface.doSomethingElse("lala");
}
}
运行结果:
doSomething
doSomethingElselala
***proxyclass com.sun.proxy.$Proxy0,method:public abstract void main.Interface.doSomthing() args: null number:1
doSomething
***proxyclass com.sun.proxy.$Proxy0,method:public abstract void main.Interface.doSomethingElse(java.lang.Object) args: [Ljava.lang.Object;@7ea987ac number:2
lala
doSomethingElselala
相信第一次接触动态代理的小伙伴一脸懵逼,什么玩意啊。好的我们来解释一下,其实这就是java对动态代理的一个实现,我们不用麻烦的去写代理类了,直接使用封装好的东西。
通过调用静态方法Proxy.newInstance()可以创建动态代理,这个方法需要得到一个类加载器,(可以通过已经被加载的类中获得,然后传递给它),一个你希望实现的接口列表(一定是接口),以及InvocationHandler接口的实现。还有一个实际的对象,我们要代理的对象。
每次调用我们动态代理类的里的方法,都会调用实现接口InvocationHandler的invoke方法,从这个方法里我们就可以做一些额外操作,这些操作可以通过判断方法名称来做区别method.getName()就可以得到当前调用的方法名。
对于得到的方法method对象调用method.invoke(proxied,args),学过反射就不难理解了。其实就是对象方法的调用
好了,这就是Java的动态代理,希望以后见到动态代理大家都不要懵逼。