---------------------- android培训、java培训、期待与您交流! ----------------------
动态代理
jvm可以在运行期动态生产出类的字节码,这种动态生成的类往往被用作代理类,即动态代理
jvm生成的动态类必须实现一个或多个接口,所以,jvm生成的动态类智能用作具有相同接口的目标类的代理
CGLIB库可以动态生成一个类的子类,一个雷的子类也可以用作该类的代理,所以,如果为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库
代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1. 在调用目标的方法之前
2. 在调用目标的方法之后
3. 在调用目标方法前后
4. 在除了目标方法异常的catch块中
Constructor[]constructors = clazzProxy.getConstructors();//获取构造方法
for (Constructorconstructor : constructors) {// 遍历构造方法
String name =constructor.getName();// 构造方法名字
StringBuildersBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[]clazzParams = constructor.getParameterTypes();//获取构造方法的参数列表
for (ClassclazzParam : 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("------------beginmethods list");
Method[] methods =clazzProxy.getMethods();// 获取方法
for (Method method :methods) {// 遍历方法
String name =method.getName();// 获取方法名
StringBuildersBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[]clazzParams = method.getParameterTypes();// 获取方法的参数列表
for (ClassclazzParam : 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("------------beginmethods list");
//clazzProxy.newInstance();
classMyInvocationHandler implements InvocationHandler {
@Override
public Objectinvoke(Object arg0, Method arg1, Object[] arg2)
throwsThrowable {
returnnull;
}
}
Constructor constructor= clazzProxy
.getConstructor(InvocationHandler.class);
//创建动态类的三种方法
Collection proxy1 =(Collection)constructor.newInstance(new MyInvocationHandler());
System.out.println(proxy1);//toString 返回了null 如果是null会报空指针异常
proxy1.clear();
// proxy1.size();//调用有返回值的方法时,会出现空指针异常
//原因分析,调用invoke时返回的是null,而该方法要求返回一个整数,无法将null转成整数所以报错
Collection proxy2 =(Collection)constructor.newInstance(new InvocationHandler(){
@Override
public Objectinvoke(Object proxy, Method method, Object[] args)
throwsThrowable {
returnnull;
}
});//使用匿名内部类
System.out.println(proxy2);
Collection proxy3 =(Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),//定义代理类的类加载器
newClass[]{Collection.class},//代理类要实现的接口列表
newInvocationHandler(){//指派方法调用的调用处理程序
ArrayListtarget = new ArrayList();
publicObject invoke(Object proxy, //调用方法的代理实例
Methodmethod,//对应于在代理实例上调用的接口方法的 Method实例
Object[]args//包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null
)throws Throwable {
longbeginTime = System.currentTimeMillis();
ObjectretVal = method.invoke(target, args);
longendTime = System.currentTimeMillis();
System.out.println("runtime:" + (time =endTime - beginTime+1));//有没有办法将 (endTime - beginTime)返回去??
returnretVal;
}
});
proxy3.add("zxx");//调动三次add,却打印四次runtime: 0??
proxy3.add("bxd");
proxy3.add("lhm");//原来每调用一次方法都会执行InvocationHandler中的invoke方法
System.out.println(proxy3.size());//调用三次add在System.out.println()中调用一次size,所以是四次
---------------------- android培训、java培训、期待与您交流! ----------------------