今天讲另一种动态代理,CGLib动态代理。前面说过,JDK动态代理能代理实现了接口的类,那如果一些类没有实现任何接口,硬是需要动态代理一批批呢?这种情况,JAVA基本类库是不管的,但我们不慌。JAVA社区这么大,还能解决不了这问题?于是CGLib来了。
      JDK动态代理的工作原理就是:根据接口,动态造一个实现类,实现一样的方法来达到代理的目的。
       CGLib没有接口,那就反向思考。上面没有我找下面。造个子类总能得相同的方法了吧。于是,造子类。动态造一个被代理类的子类做为代理类。
导包和依赖
这是一个第三方类库,所以我们要导包。
普通java项目导两个包
cglib-3.3.0.jar  和
 asm-7.1.jar
记着别漏了
asm-7.1.jar包,否则会报错

maven项目呢,依赖如下:
| <dependency><groupId>cglib</groupId>
 <artifactId>cglib</artifactId>
 <version>3.3.0</version>
 </dependency>
 
 | 
准备工作完成,下面开始套娃讲解。
   还是熟悉的配方,此时我们需要一个生产动态代理类,并造出代理对象的类。这个类得有一个属性,是被代理对象。
生产代理对象的类CGLibDynamicProxy类草稿
| public class CGLibDynamicProxy {
 //被代理对象
 
 private Object obj;
 
 //一个参数的构造方法,传入被代理对象
 
 public CGLibDynamicProxy(Object obj){
 
 this.obj=obj;
 
 }
 
 /**
 
 *
 
 * @return 代理对象。它与被代理对象实现同样的接口
 
 */
 
 public Object getProxy(){
 
 return proxy;
 
 }
 | 
我们已知,getProxy方法需要造一个子类出来,再给这个子类造一个对象。那么,怎么造子类?
Enhancer类
这里会用到这个类的三个方法:
1.   setSuperclass(Class) 字面意思:设置父类,形参是一个Class。很明显,把被代理类传进去就可以了。
2.   setCallback(Callback) 形参是一个空接口Callback。这个什么用呢?下层套娃再说,先放这里。
3.   create()。没有参数,返回一个Object。这个就是造代理类和对象的方法了。
现在,我们可以来稍微完善一下getProxy()方法了。
getProxy方法草稿
| public Object getProxy(){
 Enhancer enhancer=new Enhancer();
 
 enhancer.setSuperclass(obj.getClass());
 
 enhancer.setCallback(?);
 
 Object proxy=enhancer.create();
 
 return proxy;
 
 }
 | 
事情进展到这里,根据已有经验,还缺处理代理的方法。MethodInterceptor接口亮相的时候到了。这个接口继承了Callback接口,且必须实现的方法就一个intercept()。
intercept方法
参数:
1.   
Object 代理对象
2. Method 被代理对象要执行的方法
3. Object[] 被代理对象要执行的方法传入的参数列表
4. MethodProxy 生成的代理对象要执行的方法
返回值:
Object :执行的代理对象的方法的返回值
 
代码实现:
| 
 @Overridepublic Object intercept(Object o,
 Method method,
 Object[] objects,
 MethodProxy methodProxy)
 throws Throwable {
 System.out.println("进来代理了");
 Object result=method.invoke(obj,objects);
 System.out.println("我写日志了");
 return result;
 
 | 
此时就很明显了,我们需要一个实现了MethodInterceptor接口的类,在intercept方法中书写我们代理方法的代码。这个类自然也是实现了Callback接口的,于是可以做为Enhancer对象的setCallback方法参数。既然如此,我们不如就直接将CGLibDynamicProxy类做为MethodInterceptor接口的实现类。懒得再多写了嘛,而且还能保持优雅。
生产代理对象的类CGLibDynamicProxy类最终版
| import net.sf.cglib.proxy.Enhancer;
 import net.sf.cglib.proxy.MethodInterceptor;
 
 import net.sf.cglib.proxy.MethodProxy;
 
 
 
 import java.lang.reflect.Method;
 
 
 
 public class CGLibDynamicProxy implements MethodInterceptor {
 
 //被代理对象
 
 private Object obj;
 
 //一个参数的构造方法,传入被代理对象
 
 public CGLibDynamicProxy(Object obj){
 
 this.obj=obj;
 
 }
 
 /**
 
 *
 
 * @return 代理对象。它与被代理对象实现同样的接口
 
 */
 
 public Object getProxy(){
 
 Enhancer enhancer=new Enhancer();
 
 enhancer.setSuperclass(obj.getClass());
 
 enhancer.setCallback(this);
 
 Object proxy=enhancer.create();
 
 return proxy;
 
 }
 
 @Override
 
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
 
 begin();
 
 Object result=method.invoke(obj,objects);
 
 last();
 
 return result;
 
 }
 
 
 
 private void begin(){
 
 System.out.println("进来代理了");
 
 }
 
 private void last(){
 
 System.out.println("我写日志了");
 
 }
 
 
 
 }
 | 
客户端测试:
| public class CGLibDynamicProxyTest {public static void main(String[] args) {
 CGLibDynamicProxy cgLibDynamicProxy=
 new CGLibDynamicProxy(new ProductDaoImpl());
 IGeneralDao proxy=
 (IGeneralDao)cgLibDynamicProxy.getProxy();
 proxy.insert();
 }
 }
 
 | 
运行结果:

整个代理模式,打完收工。