看了《thinking in java》第14章 看到有动态代理这一部分内容,于是写点东西留作记忆 也算是对cglib(动态代理)的一点初识
一.没有cglib前我们是怎样的
1.首先,我们有一个接口UserMapper:
2.然后,我们写了一个类去实现它:
3.然后,我们操作这个实现类
这时 比如说来了一个问题,每个实现的方法都要其前面有一句打印时间的话,怎么办呢?
你当然可以每个方法里去加System.out.println(new Date());
但是如果用动态代理就变得简单了,你可以把这个共有的输出时间的语句抽象出来。
二.使用cglib的方法:
接着上面的步骤,那么你需要做到两步:
1.写一个类实现InvocationHandler接口(引入java.lang.reflect.InvocationHandler),这个接口需要实现一个方法
,其中第一个参数是你要代理的实际对象,在这里,就是new UserMapperImpl()对象。第二个参数用来调用method.invoke(Object obj,Object... args)方法,用来调用代理的对象中的方法,第三个参数是调用方法的参数填充,用在method.invoke()方法中的第二个参数填充
2.写完上面的类后 你还需要一个main函数去运行,在这个main函数里你需要调用Proxy(java.lang.reflect)的静态方法--Proxy.newProxyInstance(ClassLoader loader,Class<?>[ ] interfaces,InvocationHandler h)方法生成一个代理对象(返回值是Object),让后将上面的返回对象转换成UserMapper也就是接口类型,然后就可以操作这个代理的对象了,至此,cglib已经算是较为简单的实现了
三.总结
回过头来,我们需要搞清楚几个问题,或者弄清楚几个关键点。 1:cglib有什么用?答:通过对对象的代理实现调用原对象的方法前后可以加一些额外的操作 2:cglib实现有哪些关键点?答:其中比较重要的是两个方法,一个是实现InvocationHandler中的public Object invoke(Object proxy,Method method,Object[ ] args) throws Throwable{}方法,返回值是method.invoke(proxied,args),在这里有一个坑,返回值里面的proxied不是invoke方法中的第一个参数proxy,如果写成proxy会出错(我一开始吃了这个亏),
proxy代表的是代理的对象,而proxied是被代理对象,所以你可能还需要在这个实现InvocationHandler的类里面给其实现原先接口的类的实例,同时,在这个实现InvocationHandler的类里面的这个方法中,你可以将你需要在原先对象方法执行前后的操作加进去,要不然代理就没有意义了。第二个关键点就是调用Proxy的静态方法生成代理对象,这个上文有,就不多赘述了。
(本文章多用于博主自己记录看,如有错误,请指出让我改正,谢谢^^)