代理模式(四)-CGLib动态代理

时间:2023-02-24 11:07:05

今天讲另一种动态代理,CGLib动态代理。前面说过,JDK动态代理能代理实现了接口的类,那如果一些类没有实现任何接口,硬是需要动态代理一批批呢?这种情况,JAVA基本类库是不管的,但我们不慌。JAVA社区这么大,还能解决不了这问题?于是CGLib来了。

      JDK动态代理的工作原理就是:根据接口,动态造一个实现类,实现一样的方法来达到代理的目的。

       CGLib没有接口,那就反向思考。上面没有我找下面。造个子类总能得相同的方法了吧。于是,造子类。动态造一个被代理类的子类做为代理类。

导包和依赖

这是一个第三方类库,所以我们要导包。

普通java项目导两个包

cglib-3.3.0.jar  和  asm-7.1.jar

记着别漏了 asm-7.1.jar包,否则会报错

代理模式(四)-CGLib动态代理

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 :执行的代理对象的方法的返回值

代码实现:


@Override
public 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();
}
}


运行结果:

代理模式(四)-CGLib动态代理

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