第一次看到代理的时候,感觉挺晦涩的,不太清楚是个什么东西,在平时的使用的过程中也用的比较少。然而在spring的AOP编程中,觉得代理这个东西好像还挺神奇,我就特别好奇是怎么实现的,是怎么监听到一个方法的。。所以花了些时间来研究
现在有一个这样的场景,一个接口
public interface StudentInfoService {
void findInfo(String studentName);
}
一个接口的实现类
public class StudentInfoServiceImpl implements StudentInfoService {
public void findInfo(String name) {
System.out.println("你目前输入的名字是:" + name);
}
}
这个时候我某个场景调用findInfo方法的时候,我想在它之前和之后加入我自己的逻辑,就类似如下的
//before
findInfo("zs")
//after
</pre><pre>
这时候JDK的动态代理就可以帮我们搞定。
</pre><br /><pre name="code" class="java">public class AOPFactory {
private static Object getClassInstance(String clzName) {
Object obj = null;
try {
Class cls = Class.forName(clzName);
obj = (Object) cls.newInstance();
} catch (ClassNotFoundException cnfe) {
System.out.println("ClassNotFoundException:" + cnfe.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
public static Object getAOPProxyedObject(String clzName) {
Object proxy = null;
MyHandler handler = new MyHandler();
Object obj = getClassInstance(clzName);
if (obj != null) {
proxy = handler.bind(obj);
} else {
System.out.println("Can't get the proxyobj");
//throw
}
return proxy;
}
}
public class MyHandler implements InvocationHandler {
private Object proxyObj;
public Object bind(Object obj) {
this.proxyObj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
System.out.println("before");
System.out.println(method.getName());//findInfo
result = method.invoke(proxyObj, args); //通过反射执行原方法
System.out.println("after");//
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
public class ClientTest {
public static void main(String[] args) {
StudentInfoService studentInfo = (StudentInfoService) AOPFactory.getAOPProxyedObject("test.aop.StudentInfoServiceImpl");
studentInfo.findInfo("阿飞");//其实执行的就是MyHandler 的invoke方法
}
}
在这里创建的 studentInfo 实例 其实并不是test.aop.StudentInfoServiceImpl的实例,而是一个同样实现了StudentInfoService接口的另外一个类B(先叫做B),在他的findInfo方法里,执行的就是InvocationHandler 的invoke方法,并且会将test.aop.StudentInfoService的findInfo方法对象作为成员变量传递过去。
我们可以在硬盘上找到B的class文件,通过反编译代码如下
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import test.proxy.UserService;
public final class zs extends Proxy
implements UserService
{
private static Method m1;
private static Method m3;//就是findInfo方法
private static Method m0;
private static Method m2;
public zs(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 (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void findInfo()
throws
{
try
{
super.h.invoke(this, m3, null);//h就是InvocationHandler对象
return;
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return ((String)this.h.invoke(this, m2, null));
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("test.proxy.StudentInfoService").getMethod("findInfo", 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]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
这样就是整个jdk动态代理的过程