通过JDK实现动态代理,有代理需求的类(这里称之为实现类)必须要实现接口。动态代理可以将逻辑切片,通过代理类(proxy)代实现类实现逻辑,期间还可以进行一些其他的操作。JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中 InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一 起。关于动态这块儿一直比较迷惑,傻傻分不清楚,今天又有了新的理解,下面通过一个简单的例子来说明:
先叙述下事务逻辑:一个人(people对象)通过交通工具(Transportation处理类)去了外国(日本、英国)
1、将去英国和日本这两件事当做两个接口,由人来实现
package com.impetention.lei;
public interface Japan
{
public void goJapan();
}
--------------------------------------------
package com.impetention.lei;
public interface England
{
public void goEngland();
}
-------------------------------------------------
package com.impetention.lei;
//实现类
public class People implements England,Japan
{
@Override
public void goEngland()
{
// TODO Auto-generated method stub
System.out.println("I am in England !");
}
@Override
public void goJapan()
{
// TODO Auto-generated method stub
System.out.println("I am in Japan !");
}
}
2、现在介绍一下InvocationHandler ,它是代理类的调用处理程序 实现的接口。每个代理类都具有一个关联的调用处理程序,在实例化代理类时会添加进去一个InvocationHandler类型的处理类(完成事务逻辑的主题)。
如:
package com.invocation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.impetention.lei.People;
//人通过交通工具(代理)去国外
public class Transportation implements InvocationHandler
{
//一个叫zhang的人
private Object zhang = null;
public Transportation(Object zhang)
{
this.zhang = zhang;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
{
// TODO Auto-generated method stub
System.out.println("可以执行一些其他方法.....");
//记录执行结果
Object result = null;
zhang = new People();
//在zhang对象上执行method方法,并将结果返回
try
{
result = method.invoke(zhang, args);
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("---------------------");
return result;
}
}
注意里面红色的proxy,它就是代理类实例。这里有必要对invoke(Object proxy, Method method, Object[] args) 做出一些解释,动态代理类proxy0调用goEngland()方法时会调用它自己的goEngland()方法, 而它自己的goEngland()方法里面调用的是其绑定对象InvocationHandler对象的invoke()方法, 也就是Transportation的invoke方法。invoke(Object proxy, Method m, Object[] args)种的proxy实际上就是动态代理类proxy, 如果你将其强转成England然后调用它的goEngland()方法,它又会触发代理类的goEngland()方法,代理类又调用InvocationHandler(transportation)的invoke()方法,这样就会死循环。
3、代理实现:
package com.main;
import java.lang.reflect.Proxy;
import com.impetention.lei.England;
import com.impetention.lei.Japan;
import com.impetention.lei.People;
import com.invocation.Transportation;
public class Peopletest
{
public static void main(String[] args)
{
//准备用动态代理实现,一个叫li的人通过交通工具到了英国
England li = new People();
//实例化transportation对象
Transportation t1 = new Transportation(li);
//通过li.getClass().getClassLoader()实现类的类加载器和li.getClass().getInterfaces()实现类实现的所有接口作为参数调用 //Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)的方法返回代理类的java.lang.Class对象获得了一个proxy代理类, //必须给它一个InvocationHandler参数,也就是我们自己实现的用来在代理类方法执行前后做额外工作的类transpotation。将代理类强转成England类型
England proxy = (England) Proxy.newProxyInstance(li.getClass().getClassLoader(),
li.getClass().getInterfaces(), t1);
proxy.goEngland();
//准备用动态代理实现,一个叫li的人通过交通工具到了英国
Japan lei = new People();
//实例化transportation对象
Transportation t2 = new Transportation(lei);
//通过li.getClass().getClassLoader()和li.getClass().getInterfaces()获得了一个
//(java.lang.class)proxy代理类,并以tt为参数对其进行实例化,强转成people类型
Japan proxy1 = (Japan) Proxy.newProxyInstance(li.getClass().getClassLoader(),
li.getClass().getInterfaces(), t2);
proxy1.goJapan();
}
}小结:过程是这样的,people执行goEngland()方法不直接执行,而是通过代理类proxy,proxy执行它自己的goEngland(),会触发Transportation调用invoke(),然后
method.invoke(zhang, args);zhang会调用它的method,即goEngland(),最后将结果返回。
来源:https://www.cnblogs.com/90zyh/archive/2013/05/25/3099322.html