Java使用JDK与Cglib动态代理技术统一管理日志记录
Java中动态代理主要有JDK和CGLIB两种方式。
区别主要是jdk是代理接口,而cglib是代理类。
- 优点:这种方式已经解决我们前面所有日记需要的问题。非常的灵活。而且可以方便的在后期进行维护和升级。
- 缺点:当然使用jdk动态代理,必需要有接口。如果没有接口。就无法使用jdk动态代理技术。
计算接口Calculate.java
publicinterfaceCalculate{ /** *加法运算 *@paramnum1参数1 *@paramnum2参数2 *@return */ publicintadd(intnum1,intnum2); /** *加法运算 *@paramnum1参数1 *@paramnum2参数2 *@paramnum3参数3 *@return */ publicintadd(intnum1,intnum2,intnum3); /** *除法运算 *@paramnum1参数1 *@paramnum2参数2 *@return */ publicintdiv(intnum1,intnum2); }
实现计算接口中的方法CalculateImpl.java
/** *实现计算接口中的方法 *CreatedbyYongXinXueon2020/05/0511:29 */ publicclassCalculateImplimplementsCalculate{ @Override publicintadd(intnum1,intnum2){ //记录当前操作,及运算参数 LogUtils.logBefore("add",num1,num2); intresult=num1+num2; returnresult; } @Override publicintadd(intnum1,intnum2,intnum3){ //记录当前操作,及运算参数 LogUtils.logBefore("add",num1,num2,num3); intresult=num1+num2+num3; returnresult; } @Override publicintdiv(intnum1,intnum2){ //记录当前操作,及运算参数 LogUtils.logBefore("div",num1,num2); intresult=0; try{ result=num1/num2; //记录运算结果 LogUtils.logAfterReturning("div",result); }catch(Exceptione){ //记录异常信息 LogUtils.logAfterThrowing("div",e); } returnresult; } }
记录日志工具类LogUtils.java
/** *记录日志工具类 *CreatedbyYongXinXueon2020/05/0511:38 */ publicclassLogUtils{ /** *记录前置的日志操作 *@parammethod当前运算操作 *@paramargs当前运算参数 */ publicstaticvoidlogBefore(Stringmethod,Object...args){ System.out.println("操作运算是:"+method+"参数是:"+Arrays.asList(args)); } /** *返回日志操作 *@parammethod当前方法 *@paramresult当前操作返回值 */ publicstaticvoidlogAfterReturning(Stringmethod,Objectresult){ System.out.println("当前操作运算时:"+method+"返回值是:"+result); } /** *当前操作产生的异常 *@parammethod当前操作 *@parame发生的异常 */ publicstaticvoidlogAfterThrowing(Stringmethod,Exceptione){ System.out.println("当前运算时:"+method+"发生的异常是:"+e); } }
JDK动态代理的工厂类JDKProxyFactory.java
/** *JDK动态代理的工厂 *CreatedbyYongXinXueon2020/05/0513:02 */ publicclassJDKProxyFactory{ /** *通过JDK底层自带的JDK动态代理技术解决日志需求问题 *@paramtarget *@return */ publicstaticObjectcreateJDKProxy(Objecttarget){ /** *Proxy是Jdk中自带的一个工具类(反射包下,属于反射的功能). *Proxy类的作用:它可以帮我们创建代理类或实例 *方法newProxyInstance()说明:创建代理对象实例 *第一个参数是:目标对象的类加载器 *第二个参数是:目标对象实现的所有接口 *第三个参数是:InvocationHandler接口的实例 *InvocationHandler接口的实现类可以对代理的目标对象方法进行增强操作. *代理的目标对象===>>>需要额外增加功能的类(对象实例) *增强操作===>>>给原来功能添加的额外功能叫增强操作(日记就是增强操作) */ returnProxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), newInvocationHandler(){//匿名内部类 /** *invoke方法是InvocationHandler接口中唯一的方法 *代理对象每次调用方法时,都会执行invoke()方法,所有的增强操作都需要在invoke()方法中完成 *@paramproxy代理对象实例 *@parammethod代理调用的方法的反射Method对象实例 *@paramargs调用代理方法时传递进来的参数 *@return *@throwsThrowable */ @Override publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ System.out.println("代理调用了invoke方法"); System.out.println(method);//打印方法信息 System.out.println(Arrays.asList(args));//打印参数信息 //invoke()方法执行代理对象的(加法/除法/增强日志)操作 Objectresult=null; LogUtils.logBefore(method.getName(),args); try{ //1.返回值是method方法调用时的返回值 result=method.invoke(target,args); //2.增强操作 LogUtils.logAfterReturning(method.getName(),result); }catch(Exceptione){ LogUtils.logAfterThrowing(method.getName(),e); } //invoke()返回代理方法的返回值 returnresult; } }); } //测试代码 publicstaticvoidmain(String[]args){ //目标对象 Calculatetarget=newCalculateImpl(); //创建Calculate的代理对象实例 CalculatecalculateProxy=(Calculate)createJDKProxy(target); //jdk动态代理对象实例和目标对象实例同宗同族(他们都实现了相同的接口) System.out.println(calculateProxyinstanceofCalculate); System.out.println(targetinstanceofCalculate); System.out.println("代理方法的结果是:"+calculateProxy.div(100,20)); //jdk动态代理创建出来的代理对象实例是目标对象接口的一个实现类 //这个代理对象和目标对象类没有父子关系(只能用接口接收代理对象) } }
使用Cglib代理
- Jdk动态代理是通过实现目标对象所有接口产生一个代理对象实例从而解决问题.
- 如果目标对象没有接口.则可以使用Cglib动态代理技术.
- Cglib动态代理技术对目标对象有没有实现接口,没有要求.
- Cglib动态代理技术,是通过拷贝然后修改目标对象的类的字节码来产生一个代理对象
- 而且这个Cglib产生的代理对象实例是目标对象的一个子类.
IA接口IA.java
publicinterfaceIA{ publicStringshow(Stringstart); }
IA实现类IAImpl.java
publicclassIAImplimplementsIA{ @Override publicStringshow(Stringstart){ System.out.println(start+"开始表演!"); returnstart+"表演的不错!!"; } }
使用Cglib代理CglibProxyFactory.java
/** *使用Cglib代理 *CreatedbyYongXinXueon2020/05/0515:03 */ publicclassCglibProxyFactory{ publicstaticObjectcreateCglibProxy(Objecttarget){ //是Cglib用于创建代理对象的增强工具类 Enhancerenhancer=newEnhancer(); //Cglib需要对目标对象的Class字节码进行修改. //Cglib产生的代理对象实例.是目标对象的子类 enhancer.setSuperclass(target.getClass()); //只要是代理都会对原来的内容进行增强操作(增强就是在原有功能上额外添加的功能) //setCallback()设置用于增强操作的实现类(MethodInterceptor对代理方法进行拦截) //每次只要调用Cglib代理的方法,都会执行MethodInterceptor接口中intercept()方法 enhancer.setCallback(newMethodInterceptor(){ /** *intercept()方法跟JDK代理中的InvocationHandler接口中invoke()功能完全一样 *@paramproxyCglib代理对象实例 *@parammethod调用方法的反射对象实例 *@paramargs调用方法时传递的参数 *@parammethodProxy代理方法的method代理对象 *@return是代理对象方法的返回值. *@throwsThrowable */ @Override publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{ Objectresult=null; try{ LogUtils.logBefore(method.getName(),args); //调用目标方法[加/减/乘/除/或具体方法] result=method.invoke(target,args); //执行增强代码 LogUtils.logAfterReturning(method.getName(),args); }catch(Exceptione){ e.printStackTrace(); LogUtils.logAfterThrowing(method.getName(),e); } returnresult; } }); //创建Cglib代理对象实例 returnenhancer.create(); } //测试 publicstaticvoidmain(String[]args){ //目标对象 Calculatecalculate=newCalculateImpl(); //创建代理对象实例 CalculatecglibProxy=(Calculate)createCglibProxy(calculate); //调用代理方法式会执行MethodInterceptor接口中intercept()方法 intresult=cglibProxy.div(120,0); //Cglib代理是目标子类执行MethodInterceptor接口中intercept()方法 System.out.println(cglibProxyinstanceofCalculate); } }
优点:在没有接口的情况下,同样可以实现代理的效果。
缺点:同样需要自己编码实现代理全部过程。
到此这篇关于Java使用JDK与Cglib动态代理技术统一管理日志记录的文章就介绍到这了,更多相关Java动态代理统一管理日志内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!