public interface InvocationHandle {
public void invoke(Object o, Method m);
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TimeHandle implements InvocationHandle {
private Object target = null;
public TimeHandle(Object target) {
super();
this.target = target;
}
public void invoke(Object o, Method m) {
long start = System.currentTimeMillis();
try {
m.invoke(target);
System.out.println(o.getClass().getName());
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("cost time = " + (end - start));
}
}
demo2
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DemoProxy {
private Demo target=null;
public DemoProxy(Demo target) {
super();
this.target = target;
}
public Demo getDemoProxy(){
Demo proxy=null;
ClassLoader loader=target.getClass().getClassLoader();
Class interfaces[]=target.getClass().getInterfaces();
//当调用代理对象的方法时,执行的代码
InvocationHandler h=new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/**
* 不使用proxy
*/
System.out.println("logging begin");
Integer res=(Integer) method.invoke(target, args);
System.out.println("logging end");
return res;
}
};
proxy=(Demo) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
/**
* 在java种怎样实现动态代理呢
* 第一步,我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象,
* 所谓代理呢也就是在调用实现类的方法时,可以在方法执行前后做额外的工作,这个就是代理。
* 第二步,我们要自己写一个在要代理类的方法执行时,能够做额外工作的类,而这个类必须继承InvocationHandler接口,
* 为什么要继承它呢?因为代理类的实例在调用实现类的方法的时候,不会调真正的实现类的这个方法,
* 而是转而调用这个类的invoke方法(继承时必须实现的方法),在这个方法中你可以调用真正的实现类的这个方法。
* 第三步,在要用代理类的实例去调用实现类的方法的时候,写出下面两段代码。
*/
XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance(
zhangSan.getClass().getClassLoader(),
zhangSan.getClass().getInterfaces(),
new ReadyInvocationHandler(zhangSan));
proxy.xiangQin();
/**
* 这里要解释下中部那段长长的代码的意思,以及具体做了哪些工作?
* 第一,根据zhangSan.getClass().getClassLoader()这个要代理类的类加载器和
* zhangSan.getClass().getInterfaces()要代理类所实现的所有的接口
* 作为参数调用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)
* 的方法返回代理类的java.lang.Class对象,也就是得到了java动态生成的代理类$Proxy0的Class对象。
* 同时,java还让这个动态生成的$Proxy0类实现了要代理类的实现的所有接口,并继承了Proxy接口。
* 第二,实例化这个动态生成的$Proxy0类的一个实例,实例化代理类的构造函数为Proxy(InvocationHandler h),
* 也就是说要实例化这个动态生成的$Proxy0类,必须给它一个InvocationHandler参数,也就是我们自己实现的用来在代理类
* 方法执行前后做额外工作的类ReadyInvocationHandler。
* 这段代码Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan))
* 得到的其实是一个类名叫$Proxy0 extends Proxy implements XiangQinInterface的类。
* 第三,将这个$Proxy0类强制转型成XiangQinInterface类型,调用xiangQin方法。
*/
Cglib动态代理
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
class Handler {
public void say() {
System.out.println("Handler");
}
}
class CglibHandler implements MethodInterceptor {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println("CglibHandler");
return arg3.invokeSuper(arg0, arg2);
}
}
class CglibFactory {
public static <T> Object createProxy(Class<T> clazz, CglibHandler handler) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(handler);
return (T) enhancer.create();
}
}
public class Main {
public static void main(String[] args) {
Handler handler=(Handler) CglibFactory.createProxy(Handler.class, new CglibHandler());
handler.say();
}
}
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。针对每个方法。
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
cglib 创建某个类A的动态代理类的模式是:
1. 查找A上的所有非final 的public类型的方法定义;
2. 将这些方法的定义转换成字节码;
3. 将组成的字节码转换成相应的代理的class对象;
4. 实现 MethodInterceptor接口,用来处理 对代理类上所有方法的请求(这个接口和JDK动态代理InvocationHandler的功能和角色是一样的)
5.
静态代理和动态代理
动态代理
动态编程,需要在原来的方法的功能基础上再添加一些功能,而不用改变这个方法的签名,原来调用这个方法的类依然能正常工作。
比如,现在要把一段文本发送给另一个人,普通方法是 void send(File a),现在我们弄出个特性,就像 Spring AOP 那样,在 send 之前给这个 a 压缩一下。原来的程序没有压缩功能,现在我们需要添加的话而不改变原来所有的代码的话就得用类似 AOP 这样的代码来处理。
一般一个无法再继承的类和方法,要用代理,而能够继承的类和方法可以在内在中直接生成一个新的 java 类继承它然后覆盖掉那个 send 方法,像 hibernate/spring/jboss 都把这些自动完成了。
而像 AspectJ 这种 AOP 刚不同,它直接把人家的 class 代码修改了,它就不需要使用代理。
在不需要原来的作者明确改动代码的情况下添加新功能。比如你没有原来的代码但想添加新功能,或者你需要的新功能仅用于某个地方而原来的功能用到更多的地方,所以不打算修改原来的功能而只是定制你新加的这部分,那么使用 AOP 原来的代码不需要修改,你只需要配置 AOP 并新增你自己的功能,重新编译一下就好了。你听说过 Hibernate Lazy Initialization 吧,这叫延迟加载,也就是当一个对象有很多 detail 表时,以前自动把 detail 表的数据全抓取了导致这些对象可能没有被使用而浪费时间或浪费内存,于是懒加载的想法出现了,为了让懒加载对用户编程来说是透明的,你不需要明确的写代码实现它,Hibernate 是使用 AOP 来解决的。你的代码没有为此作出任何改变但新功能添加上来了