动态代理老是忘,偏偏这玩意还阴魂不散,Struts2里有,mybatis里有,Spring的aop更是以动态代理为主要实现,所以写一篇备忘,还加了一点spring的内容
interface Cal{int add(int i,int j);}//接口
class jisuan implements Cal{int add(i,j){return i+j;}}//实现接口
实现InvocationHandler:
public class ProxyDemo implements InvocationHandler{
public Cal cal;
public ProxyDemo(Cal cal) {
this.cal=cal;
}
public Object invoke(Object proxy/*在其上调用方法的代理实例,也就是生成的com.sun.proxy.$Proxy0类*/, Method method/*在代理实例上调用的接口方法的 Method实例*/, Object[] args) throws Throwable {
System.out.println("计算"+args[0]+"+"+args[1]);
Object obj=null;
try{
//@Before
obj=method.invoke(cal,args);//反射,传入代理对象cal和参数列表args
//@AfterRunning
}catch(Exception e){
@AfterThrowing
}
//@After,因为可能产生异常,所以获取不到方法返回值
System.out.println("结果为:"+obj);
return obj;//返回值为执行结果返回值,若为void则返回null
}
}
执行调用:
Jisuan j=new Jisuan();
InvocationHandler handler=new ProxyDemo(j);
Cal j2 =(Cal)Proxy.newProxyInstance(j.getClass().getClassLoader(),j.getClass().getInterfaces(), handler);
int result=j2.add(1,1);//实际上相当于执行了ProxyDemo里的invoke方法
System.out.println(result);
动态代理首先必须有个接口或者父类,比如Cal,因为实际上代理类(名字叫com.sun.proxy.$Proxy0)相当于拓展了Cal并重写了add方法,并类似这样实现:
class $Proxy0 implements Cal{
int add(i,j){
System.out.println("计算"+i+"+"+j);
int result=i+j;
System.out.println("结果为:"+result);
return result;
}
}
*动态代理作用于Cal里所有方法,甚至是toString()