JDK动态代理还是需要被代理对象实现特定的接口,为了解决这一缺陷,可使用cglib动态代理的方式解决。
cglib动态代理
实例:
代码:
package cglibProxy;
public class Studtent {
public String study(String subject) {
System.out.println("study"+subject+"中......");
return subject;
}
}
package cglibProxy;
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 StudentProxy implements MethodInterceptor {
// 获取代理对象,参数为目标对象的Class类对象
public Object getProxy(Class target){
// 以下四句代码记住即可,反正就是创建代理类对象的方法,底层不要多在意
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target);
enhancer.setCallback(this);
return enhancer.create();
}
// 重写intercept方法
// 参数分别为代理对象,目标对象方法,方法参数,代理对象方法
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 增强方法
System.out.println("准备学习了!");
// 利用反射机制,通过代理对象的方法,实现目标对象的方法调用,这里可以有其他代码方式,后面介绍
Object invoke1 = methodProxy.invokeSuper(proxy, args);
// 增强方法
System.out.println("一个小时过去了,学习完了!");
// 返回方法执行后的返回值
return invoke1;
}
}
package cglibProxy;
public class Test {
public static void main(String[] args) {
Studtent target = new Studtent();
// 创建代理对象,注意用到了强转
Studtent student_proxy = (Studtent) new StudentProxy().getProxy(target.getClass());
// 执行目标对象的方法,增强过的,并且有返回值
String subject1 = student_proxy.study("中文");
// 输出返回值,就是传入的参数
System.out.println(subject1);
}
}
结果:
另外一种代码:
注意这句代码,这个是使用代理对象方法,传入的是代理对象和方法参数,那么可不可以使用目标对象的invoke,传入目标对象和参数呢?是可以的,只是代码略微不同,要修改获取代理对象的代码,且Test也有所变化:
Object invoke1 = methodProxy.invokeSuper(proxy, args);
代码修改:
package cglibProxy;
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 StudentProxy implements MethodInterceptor {
// 要Object invoke1 = method.invoke(target, args);而修改代码
private Object target;
public StudentProxy(Object target) {
this.target = target;
}
// 获取代理对象
public Object getProxy(){
// 以下四句代码记住即可,反正就是创建代理类对象的方法,底层不要多在意
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
// 重写intercept方法
// 参数分别为代理对象,目标对象方法,方法参数,代理对象方法
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 增强方法
System.out.println("准备学习了!");
// 利用反射机制,实现目标对象的方法调用
// Object invoke1 = methodProxy.invokeSuper(proxy, args);
Object invoke1 = method.invoke(target, args);//目标对象方法
// 增强方法
System.out.println("一个小时过去了,学习完了!");
// 返回方法执行后的返回值
return invoke1;
}
}
package cglibProxy;
public class Test {
public static void main(String[] args) {
Studtent target = new Studtent();
// 创建代理对象,注意用到了强转
Studtent student_proxy = (Studtent) new StudentProxy(target).getProxy();
// 执行目标对象的方法,增强过的,并且有返回值
String subject1 = student_proxy.study("中文");
// 输出返回值,就是传入的参数
System.out.println(subject1);
}
}
关于使用cglib代理的jar包问题
cglib代理需要一些jar包:
对于我这样的小白来说,这算是一个很无语的事情,因为书上没有说在哪里下载包,于是网上直接搜索cglib jar包,于是让人更无语的事情发生了:
总之就是要么找不到,要么需要money!我就奇怪了,都是开源的,干嘛非得这样!
于是搜索其他方式,后来有人说直接去maven网站上去找就行了:
maven中各种jar包
其他需要的包写这样下载,然后添加到项目中就可以了。
这里需要注意,各个包之间或者单独的包可能存在问题,因此运行时可能会出现问题。
我这里使用的四个包如下,但是运行时依然出现了警告,刚开始使用cglib3.0版本以上直接报错:
这次深刻的体会到jar包导入的问题,这或许就是后来有了maven的原因,maven可以有效解决各种依赖包的问题。