续spring源码阅读(2)-aop之j动态代理
我们从需求作为动态代理发展的切入吧
现在有5个已经投产了的run100m的实现,我们新的需求需要监控不同实现的运行性能,如果我们针对这五个实现分别去添加性能监控的代码,如此就造成两个问题:
一个是已经稳定的代码需要重新测试,
一个是设计上相同的代码出现在项目的各个地方,以后需要修改就需要修改5个地方,如果有新加实现就需要修改更多的处理点。
伟大的程序设计大师早就解决了这个问题,我们可以代理的方式,也就是我们的代理模式,我们来看下代理的uml类图
上面是一个代理的uml类关系图, 我们来看下ProxyRace的伪代码大概就清楚代理了
public class ProxyRace implement Race{
private Race race;
@Override
public void race100m(){
performancemonitor.start();
race.run100m();
performancemonitor.end();
}
}
看到这里对静态代理是不是一下就清晰了。
代理的关键在于接口,代理,实现类都实现了相同的接口,代理类关联了一个实现类,由代理去调用实现类的方法,如此代理类就可以添加自己的业务了。
回到性能监控的需求上面,可见使用代理的模式是不是使上面的需求一下变得简单易于维护了,以后对于性能监控的代码只要修改代理类这一处就ok了。也减少了代码的改动点,从而减少测试工作,并且以后的实现还是只要关注run100m的业务就好,不用关注性能方面的业务,也免去了其他业务代码的侵入,松了耦合。
如果我们以后不断的在各种现有实现功能的基础上做各种代理操作,也会造成代理类的数量过多的情形,此时我们就想要做一个通用的代理工具:
这就引出了一个我们这篇博文需要重点讨论的问题:动态代理
从上面的代理我们得出,代理某个类我们需要新建一个代理类对接口功能做包括:所以动态代理就需要支持一个非常重要的功能,动态创建类。
然后我们再想想jdk的Proxy.newProxyInstance的实现原理
从InvocationHandler的invoke方法分析:(我们是在这个接口方法里做代理业务处理的)
public Object invoke(Object proxy, Method method, Object[] args){
method.invoke(target, args);
}
然后根据我们实现的静态代理类如何改造成上面的结构:
新建一个InvocationHandler类,把race属性移到这个类里,且这个类添加一个方法invoke(method,arg),我们再改造ProxyRace,添加一个方法newProxyInstance方法,我们编写一个伪代码
newProxyInstance(Class itfs, invocationHandler){
invocationHandler.invoke(method, );
//制作一个类字符串
String classStr = public class $Proxy1 implements itfs{
private InvcationHander ih;
//构造方法传入invocationHandler
public $Proxy(InvocationHander ih){
this.ih = it;
}
//遍历接口的所有方法
for (Method m:itfs.getMethods()){
public void m.getName()(){
//这个里面调用invocationHandler的invoke方法,注意这里是对象直接调用
ih.invoke(this, m);
}
}
}
//写入到文件
File clsf = createClassFile(classStr);
//java编译
CompileClassFile(clsf);
//使用类加载器加载类
loadclass();
}
这个是简略写的jdk反射的原理概要,再次确认了接口对于jdk太重要了,所有的核心操作都是针对接口设计的,
在看看cglib实现的动态代理
cglib实现的原理与jdk稍微有点不一样,jdk是基于接口的关联的方式实现的代理,而cglib是继承的方式,子类覆盖父类方法实现代理
我们来看看cglib针对如上业务的实现吧
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer;
private long startt;
public Object getProxy(Class proxyClass){
enhancer = new Enhancer();
enhancer.setSuperclass(proxyClass);
enhancer.setCallback(this);
return enhancer.create();
}
private void begin(){
this.startt = System.currentTimeMillis();
System.out.println("开始时间:" + this.startt);
}
private void end(){
long endt=System.currentTimeMillis();
System.out.println("结束时间:"+endt+" 执行消耗:"+(endt-startt));
}
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
begin();
Object ret = methodProxy.invokeSuper(target, args);
end();
return ret;
}
}
执行结果
开始时间:1539966285203
human run 100m
结束时间:1539966295222 执行消耗:10019
使用System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\\\swap");生成代理类class
我们看看看看这个class内容
public class HumanRace$$EnhancerByCGLIB$$bb1a6f1f extends HumanRace implements Factory {
final void CGLIB$race100m$0() {
super.race100m();
}
public final void race100m() {
//回调类实现了MethodInterceptor接口
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
var10000.intercept(this, CGLIB$race100m$0$Method, CGLIB$emptyArgs, CGLIB$race100m$0$Proxy);
super.race100m();
}
final boolean CGLIB$equals$2(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$3() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
}
final int CGLIB$hashCode$4() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$5() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
}
//这里在enhancer.setCallback();中设置的回调
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
}
从这个类我们应该能看出cglib的实现原理,我们根据我们的实现代码加上这个类慢慢剖析:
public class HumanRace$$EnhancerByCGLIB$$bb1a6f1f extends HumanRace
这里继承了我们要代理的类,印证了cglib的代理是基于继承的,我们继续看看继承是如何实现代理的
public void setCallback(int var1, Callback var2)
我们应用中有一个enhancer.setCallback(this);就是设置的一个回调类,我们继续看看这个类怎么使用的
final void CGLIB$race100m$0() {
super.race100m();
}
public final void race100m() {
//回调类实现了MethodInterceptor接口
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 != null) {
var10000.intercept(this, CGLIB$race100m$0$Method, CGLIB$emptyArgs, CGLIB$race100m$0$Proxy);
} else {
super.race100m();
}
}
从这个类看每个方法都实现了两个,一个使用了一个做了下别名,一个就是原方法名,我们只研究我们关注的方法,其他的toString,equal之类的我们暂不看。
CGLIB$race100m$0()根据cglib的一个规则重新命名,直接调用父类的super.race100m()方法,一个是覆盖了父类的方法,这里使用了我们上面的回调,如果回调不为空,调用回调是实现的intercept方法,我们就是在这个方法了实现代理的。
至此cglib的实现原理和方式我想您也应该清楚了吧。