何为动态署理?
在程序运转期,创立目标目标的署理目标,对目标目标中的办法进行功用性增强的一种技术;它便是JVM中,目标办法的阻拦器
writelessdomore!!
回顾OOP(面向目标编程)
三大特征:封装、承继和多态比如说,有Dog类、Cat类、Horse类,它们都有eat办法,run办法,依照OOP的编程思维,那么咱们能够抽象出父类Animal,在父类中放置相同的特点或者办法,这样来防止多子类中重复的代码。一切皆目标,很牛逼了,其实它有缺点!
OOP是纵向抽取和承继体系,OOP许多场合都能够处理咱们的问题【代码重复问题】,但是有一些场合,也有它处理不了的需求被处理的很多的代码重复问题。
1.1什么是动态署理?
==动态署理便是,在程序运转期,创立目标目标的署理目标,并对目标目标中的办法进行功用性增强的一种技术==。在生成署理目标的过程中,目标目标不变,署理目标中的办法是目标目标办法的增强办法。能够理解为运转期间,目标中办法的动态阻拦,在阻拦办法的前后履行功用操作。
署理类在程序运转期间,创立的署理目标称之为动态署理目标。这种情况下,创立的署理目标,并不是事先在Java代码中界说好的。而是在运转期间,依据咱们在动态署理目标中的“指示”,动态生成的。也便是说,你想获取哪个目标的署理,动态署理就会为你动态的生成这个目标的署理目标。动态署理能够对被署理目标的办法进行功用增强。有了动态署理的技术,那么就能够在不修正办法源码的情况下,增强被署理目标的办法的功用,在办法履行前后做任何你想做的工作。
创立署理目标的两个办法:
//JDK动态署理
Proxy.newProxyInstance(三个参数);
//CGLib动态署理
Enhancer.create(两个参数);
正常类创立目标的过程:
动态署理创立署理目标的过程:
1.2两种常用的动态署理办法
根据接口的动态署理提供者:JDK运用JDK官方的Proxy类创立署理目标留意:署理的目标目标有必要完成接口根据类的动态署理提供者:第三方CGLib运用CGLib的Enhancer类创立署理目标留意:如果报asmxxxx反常,需求导入asm.jar包publicclassLogProxy{
/**
*生成目标的署理目标,对被署理目标进行一切办法日志增强
*参数:原始目标
*返回值:被署理的目标
*JDK动态署理
*根据接口的动态署理
*被署理类有必要完成接口
*JDK提供的
*/
publicstaticObjectgetObject(finalObjectobj){
/**
*创立目标的署理目标
*参数一:类加载器
*参数二:目标的接口
*参数三:调用处理器,署理目标中的办法被调用,都会在履行办法。对一切被署理目标的办法进行阻拦
*/
ObjectproxyInstance=Proxy.newProxyInstance(obj.getClass().getClassLoader()
,obj.getClass().getInterfaces(),newInvocationHandler(){
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
//办法履行前
longstartTime=System.currentTimeMillis();
Objectresult=method.invoke(obj,args);//履行办法的调用
//办法履行后
longendTime=System.currentTimeMillis();
SimpleDateFormatsdf=newSimpleDateFormat();
System.out.printf(String.format("%s办法履行结束时间:%%s;办法履行耗时:%%d%%n"
,method.getName()),sdf.format(endTime),endTime-startTime);
returnresult;
}
});
returnproxyInstance;
}
/**
*运用CGLib创立动态署理目标
*第三方提供的的创立署理目标的办法CGLib
*被署理目标不能用final修饰
*运用的是Enhancer类创立署理目标
*/
publicstaticObjectgetObjectByCGLib(finalObjectobj){
/**
*运用CGLib的Enhancer创立署理目标
*参数一:目标的字节码文件
*参数二:办法的阻拦器
*/
ObjectproxyObj=Enhancer.create(obj.getClass(),newMethodInterceptor(){
publicObjectintercept(Objecto,Methodmethod,Object[]objects,MethodProxymethodProxy)throwsThrowable{
//办法履行前
longstartTime=System.currentTimeMillis();
ObjectinvokeObject=method.invoke(obj,objects);//履行办法的调用
//办法履行后
longendTime=System.currentTimeMillis();
SimpleDateFormatsdf=newSimpleDateFormat();
System.out.printf(String.format("%s办法履行结束时间:%%s;办法履行耗时:%%d%%n"
,method.getName()),sdf.format(endTime),endTime-startTime);
returninvokeObject;
}
});
returnproxyObj;
}
}
.