------- android培训、java培训、期待与您交流! ----------
1 基本概念理解
代理,这个名词在生活中很常见,如厂家生产的货品出售的时候会选择一些代理厂商帮助它出售自己的商品,这里厂商和代理都能完成出售商品这一共同目标,而且代理可以分布在各地,对厂商来讲有利于扩展销售群体,对买家来讲,方便自己的购物;在程序中的体现形式则是:为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能,如异常处理,日志,计算方法的运行时间,事务管理等。
示例如下:
class Sailing//该示例仅作为说明代理的概念和理解
{
Void sail()
{
System.out.println("卖出商品");
}
}
//下面是代理类
class ProxySailing
{
Void sail()
{
sailTime;//出售时间
System.out.println("卖出商品");
}
}
AOP,即面向切面的编程,系统中出现的交叉业务,如安全、事物、日志等,在编程的时候很多模块都会涉及到这些方面,但是将这些模块放到所有的实体对象中,又不合适,这时候我们就可以将这些功业务功能模块化。代理是实现AOP编程的核心和关键技术。
在代理方法中的如下四个位置加上系统功能代码:在调用目标方法之前;在调用目标方法之后;在调用目标方法前后;在处理目标方法异常的catch块中。
2 代理的使用
JVM可以在运行期间动态生成出类的字节码,这种动态生成的类被使用做代理类,即动态代理类 ,而且JVM生成的动态类只能作具有相同接口的目标类的代理(必须生成一个或多个接口。
表示动态代理的类,提供两个静态方法:
a Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,用来表示真实的对象。
b Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法,invoke方法就是来执行功能代码的地方。
使用 Java 动态代理的具体如下:
通过实现 InvocationHandler 接口创建自己的调用处理器;
通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
而在实际过程中由于Proxy 的静态方法 newProxyInstance 已经为我们封装了步骤 2 到步骤 4 的过程,因而使用过程更加简单。示例如下:
InvocationHandler handler = new InvocationHandlerImpl(..); // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,
new Class[] { Interface.class },
handler );
下面用一个完整的程序来具体说明代理的使用过程
package com.itheima;
//导入包
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
class ProxyTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//调用Proxy类的获取代理类方法,指定类加载器,多个接口,通常采用与接口相对应的类加载器,返回的是一个字节码的类
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy1.getName());//打印代理类名
System.out.println("----------begin print constructors list----------");
Constructor[] constructors = clazzProxy1.getConstructors();//获取该对象的构造函数,返回一个集合
for(Constructor constructor : constructors){//使用高级for循环 获取构造函数的名称和变量类型信息
String name = constructor.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = constructor.getParameterTypes();//获取变量类型
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');//变量输出时中间用,隔开
}
if(clazzParams!=null && clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());//打印变量
}
System.out.println("----------begin print methods list----------");
Method[] methods = clazzProxy1.getMethods();//获取方法,返回一个Method类型的数组
for(Method method : methods){//使用高级for循环,打印方法信息
String name = method.getName();//获取方法名
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = method.getParameterTypes();//获取变量类型信息
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length != 0)//如果变量不为null并且长度不为0 ,去掉最后的一个","
sBuilder.deleteCharAt(sBuilder.length()-1);//显示的时候美观一些
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("----------begin create instance object----------");
//Object obj = clazzProxy1.newInstance();
Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
class MyInvocationHander1 implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;//返回最简单的实现 ,返回值null
}
}
//获取collection类型的对象
Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());
System.out.println(proxy1);
proxy1.clear();//清除集合
//传递匿名内部类形式的InvocationHandler对象作为参数
Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});
final ArrayList target = new ArrayList();//定义集合类型的目标对象
Collection proxy3 = (Collection)getProxy(target,new MyAdvice());
proxy3.add("zxx");//添加元素
proxy3.add("lhm");
proxy3.add("bxd")
System.out.println(proxy3.size());//获取长度
System.out.println(proxy3.getClass().getName());//获取代理类名
}
private static Object getProxy(final Object target,final Advice advice) {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),//加载目标类的加载器
/*new Class[]{Collection.class},*/
target.getClass().getInterfaces(),//获取目标对象的所有接口
new InvocationHandler(){//采用匿名内部类方法得到Handler对象
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
}
);
return proxy3;//返回该代理
}
}