今天讲另一种动态代理,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 代理对象
3. Object[] 被代理对象要执行的方法传入的参数列表
4. MethodProxy 生成的代理对象要执行的方法
返回值:
代码实现:
@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(); } }
|
运行结果:
整个代理模式,打完收工。