------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
程序中的代理
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法运行时间、事务管理、等等
编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能代码。(参看下面的原理图)
如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后想去掉系统功能也很容易
package cn.itcast.day3;
import java.lang.reflect.Method;
/*
* 定义一个忠告,实现系统功能,也叫建议,是插入进来或切入进来的建议
*/
public interface Advice {
void beforeMethod(Method method);//定义一个在方法执行之前的抽象方法
void afterMethod(Method method);//定义一个在方法执行之后的抽象方法
}
package cn.itcast.day3;
import java.lang.reflect.Method;
/*
* 实现Advice
*/
public class MyAdvice implements Advice {
long beginTime = 0;
public void afterMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("从传智播客毕业上班啦!");
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + " running time of " + (endTime - beginTime));
}
public void beforeMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("到传智播客来学习啦!");
beginTime = System.currentTimeMillis();
}
}
package cn.itcast.day3;
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;
public class ProxyTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
/*
* 调用proxy这个类,有一个静态方法getProxyClass,
* 为它指定一个类加载器,Collection接口
*/
/*
* JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
* 创建出了这样一个动态代理类
*/
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
//获得这个动态代理类的名称:$Proxy0
System.out.println(clazzProxy1.getName());
System.out.println("----------begin constructors list----------");
/*$Proxy0()
$Proxy0(InvocationHandler,int)*/
//取这个动态代理类下的所有构造函数
Constructor[] constructors = clazzProxy1.getConstructors();
for(Constructor constructor : constructors){
//获得构造函数名
String name = constructor.getName();
//加入sBuilder中
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
//获得构造函数的参数列表
Class[] clazzParams = constructor.getParameterTypes();
for(Class clazzParam : clazzParams){
//将参数完整的类名加入sBuilder中
sBuilder.append(clazzParam.getName()).append(',');
}
//这个参数列表不为空,且参数数组的长度不为0
if(clazzParams!=null && clazzParams.length != 0)
//删除逗号
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
//生成的动态代理类有构造方法 $Proxy0(java.lang.reflect.InvocationHandler)
System.out.println(sBuilder.toString());
}
System.out.println("----------begin methods list----------");
/*$Proxy0()
$Proxy0(InvocationHandler,int)*/
//获取这个动态代理类的所有方法
Method[] methods = clazzProxy1.getMethods();
for(Method method : methods){
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)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
/*
* add(java.lang.Object)
equals(java.lang.Object)
toString()
...
*/
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;
}
}
//用这个构造方法去new一个instance,传入一个具体的参数:new MyInvocationHander1()
//有了Collection这个对象
Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());
System.out.println(proxy1);//结果为null
proxy1.clear();//调用无返回值的方法,成功
//proxy1.size();//调用有返回值的方法,失败,报空指针异常
//System.out.println("111111111111111");
//new一个动态类的实例对象
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());//指定一个目标ArrayList对象
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(),//获得这个目标ArrayList对象的类加载器
/*new Class[]{Collection.class},//多个接口*/
target.getClass().getInterfaces(),//获得这个目标ArrayList对象的所有接口
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + " running time of " + (endTime - beginTime));
return retVal;*/
/*
* 为目标类的方法增加一个系统功能,即计算方法的运行时间
*/
//在方法执行之前执行这个方法,实现系统功能
advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
//在方法执行之后执行这个方法,实现系统功能
advice.afterMethod(method);
return retVal;
}
}
);
return proxy3;
}
}