1 什么是代理模式?
为其他对象提供一种代理以控制对这个对象的访问。
2 代理模式有什么好处?
在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法)。
动态代理的流程图:
代码:
定义接口:
public interface people {
public List eat();
public void sport();
}
接口的实现类:
public class zhangsanimplements people {
public List eat() {
System.out.println("张三在吃饭!");
List list=new ArrayList();
list.add("haha");
return list;
}
public void sport() {
}
}
现在我想对这个类的eat()方法增强一些功能而又不改变源代码(例如事务控制、日志等),这时需要一个ProxyHandler类它实现了InvocationHandler接口,在这个类的invoke方法中处理业务:
public class ProxyHandlerimplements InvocationHandler {
private peoplepe;
public ProxyHandler(people p)
{
pe=p;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before();
method.invoke(pe,null);
after();
//这个method的方法就是你要增强的类中eat();方法了。
注意这个method的invoke,是method类的invoke(pe, null)
方法,意思是掉用pe这个类的method方法。
return null;
}
public void before()
{
System.out.println("吃饭前洗手!");
}
public void after()
{
System.out.println("吃饭后刷碗!");
}
}
写个测试类:
public static void main(String[] args)throws IOException {
people p=(people) Proxy.newProxyInstance(people.class.getClassLoader(),new Class[] {people.class},new ProxyHandler(new zhangsan()));
p.eat();
}
现在这个 p.eat();怎么就可以调用ProxyHandler类里的invoke();从而达到代理目的呢?
1.首先 Proxy.newProxyInstance(people.class.getClassLoader(),new
Class[]{people.class},new ProxyHandler(new zhangsan()));
这个方法干了什么?它是在内存中生成了一个$Proxy0.class类。
接下来看看这个类:
import DynamicProxy.people;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;
public final class $Proxy0 extends Proxy
implements people
//这个类继承了Proxy类并且实现了people接口,这个people接口就是Proxy.newProxyInstance(people.class.getClassLoader(), new Class[] {people.class},new ProxyHandler(new zhangsan())); 传的接口数组
{
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m4;
private static Method m2;
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("DynamicProxy.people").getMethod("eat", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m4 = Class.forName("DynamicProxy.people").getMethod("sport", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
//这里的m3,m4就是people接口里的函数了
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
//这里当调用 p.eat();时 就会调用 $Proxy0的这个eat()方法了
即: return (List)this.h.invoke(this, m3, null);这个语句
而这个h在$Proxy0这个父类Proxy类中是protected InvocationHandlerh;
也就是 Proxy.newProxyInstance(people.class.getClassLoader(),new Class[]{people.class},new ProxyHandler( new zhangsan()));中我们传入的代理类ProxyHandler了,这样就会调到我们用以增强函数的那个invoke()方法了
public final List eat()
throws
{
try
{
return (List)this.h.invoke(this, m3, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void sport()
throws
{
try
{
this.h.invoke(this, m4, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
}