public interface UserService {
/**
* 目标方法
*/
public abstract void add();
}
public class UserServiceImpl implements UserService {
/* (non-Javadoc)
* @see dynamic.proxy.UserService#add()
*/
public void add() {
System.out.println("--------------------add---------------");
}
}
public class MyInvocationHandler implements InvocationHandler {
// 目标对象
private Object target;
/**
* 构造方法
* @param target 目标对象
*/
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
/**
* 执行目标对象的方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在目标对象的方法执行之前简单的打印一下
System.out.println("------------------before------------------");
// 执行目标对象的方法
Object result = method.invoke(target, args);
// 在目标对象的方法执行之后简单的打印一下
System.out.println("-------------------after------------------");
return result;
}
}
public class ProxyTest {
@Test
public void testProxy() throws Throwable {
// 实例化目标对象
UserService userService = new UserServiceImpl();
// 实例化InvocationHandler
MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
// 根据目标对象生成代理对象,参数为:一个classloader,一个接口数组,一个invocationHandler
UserService proxy = (UserService)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),userService.getClass().getInterfaces(), invocationHandler );
// 调用代理对象的方法
proxy.add();
}
}
当你刚看到动态代理时,会感到非常疑惑与混乱。但最终的结果告诉我们,最后执行的代码是invocationHandler.invoke方法:
System.out.println("------------------before------------------");
// 执行目标对象的方法
Object result = method.invoke(target, args);
// 在目标对象的方法执行之后简单的打印一下
System.out.println("-------------------after------------------");
通过查看Proxy.newProxyInstance方法的源码,我发现,有用的就两句话,大概意思是:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
Class proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
Constructor cons = proxyClass.getConstructor(InvocationHandler.class);
return (Object) cons.newInstance(new Object[] { invocationHandler });
java用Proxy.newInstance的第二个参数:接口数组,构造了一个新的class,并且返回了一个用该class构造的一个新的对象,通过反编译工具,来将该class文件反编译为一个java文件,来看看究竟:
public final class $Proxy11 extends Proxy implements UserService
{
public $Proxy11(InvocationHandler invocationhandler)
{
super(invocationhandler);
}
public final boolean equals(Object obj)
{
try
{
return ((Boolean)super.h.invoke(this, m1, new Object[] {
obj
})).booleanValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
@这个方法是关键部分@
public final void add()
{
try
{
super.h.invoke(this, m3, null);
return;
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode()
{
try
{
return ((Integer)super.h.invoke(this, m0, null)).intValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString()
{
try
{
return (String)super.h.invoke(this, m2, null);
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m2;
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
Class.forName("java.lang.Object")
});
m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
}
catch(NoSuchMethodException nosuchmethodexception)
{
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
}
catch(ClassNotFoundException classnotfoundexception)
{
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
}
也就是说当我们调用proxy.add()方法时,add方法的代码为:
super.h.invoke(this, m3, null);
super.h:
h也就是我们我们构造这个类时传入的参数,上面提到过,具体代码如下:
return (Object) cons.newInstance(new Object[] { invocationHandler });
一个我们定义过的类的实例。
m3:
m3 = Class.forName(“dynamic.proxy.UserService”).getMethod(“add”, new Class[0]);
现在一切就很清晰明了了吧,知其然知其所以然,现在就可以灵活运用java动态代理了。
参考文章:http://rejoy.iteye.com/blog/1627405