栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java使用JDK与Cglib动态代理技术统一管理日志记录

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java使用JDK与Cglib动态代理技术统一管理日志记录

Java中动态代理主要有JDK和CGLIB两种方式。

区别主要是jdk是代理接口,而cglib是代理类。

  • 优点:这种方式已经解决我们前面所有日记需要的问题。非常的灵活。而且可以方便的在后期进行维护和升级。
  • 缺点:当然使用jdk动态代理,必需要有接口。如果没有接口。就无法使用jdk动态代理技术。

计算接口 Calculate.java

public interface Calculate {
 
 public int add(int num1, int num2);

 
 public int add(int num1, int num2, int num3);

 
 public int div(int num1, int num2);
}

实现计算接口中的方法 CalculateImpl.java


public class CalculateImpl implements Calculate {
 @Override
 public int add(int num1, int num2) {
  // 记录当前操作,及运算参数
  LogUtils.logBefore("add", num1, num2);
  int result = num1 + num2;
  return result;
 }

 @Override
 public int add(int num1, int num2, int num3) {
  // 记录当前操作,及运算参数
  LogUtils.logBefore("add", num1, num2, num3);
  int result = num1 + num2 + num3;
  return result;
 }

 @Override
 public int div(int num1, int num2) {
  // 记录当前操作,及运算参数
  LogUtils.logBefore("div", num1, num2);
  int result = 0;
  try {
   result = num1 / num2;
   // 记录运算结果
   LogUtils.logAfterReturning("div", result);
  }catch (Exception e){
   // 记录异常信息
   LogUtils.logAfterThrowing("div", e);
  }
  return result;
 }
}

记录日志工具类 LogUtils.java


public class LogUtils {
 
 public static void logBefore(String method, Object ... args){
  System.out.println("操作运算是 : " + method + " 参数是 : " + Arrays.asList(args));
 }

 
 public static void logAfterReturning(String method, Object result){
  System.out.println("当前操作运算时 : " + method + " 返回值是 : " + result);
 }

 
 public static void logAfterThrowing(String method, Exception e){
  System.out.println("当前运算时 : " + method + " 发生的异常是 : " + e);
 }
}

JDK 动态代理的工厂类 JDKProxyFactory.java


public class JDKProxyFactory {

 
 public static Object createJDKProxy(Object target){
  
  return Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    target.getClass().getInterfaces(),
    new InvocationHandler() { // 匿名内部类
     
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println("代理调用了 invoke 方法 ");
      System.out.println(method);  //打印方法信息
      System.out.println(Arrays.asList(args)); //打印参数信息
      // invoke() 方法执行代理对象的(加法 / 除法 / 增强日志)操作
      Object result = null;
      LogUtils.logBefore(method.getName(), args);
      try {
// 1. 返回值是 method 方法调用时的返回值
result = method.invoke(target, args);
// 2. 增强操作
LogUtils.logAfterReturning(method.getName(), result);
      }catch (Exception e){
LogUtils.logAfterThrowing(method.getName(), e);
      }
      // invoke() 返回代理方法的返回值
      return result;
     }
    });
 }

 // 测试代码
 public static void main(String[] args) {
  // 目标对象
  Calculate target = new CalculateImpl();
  // 创建 Calculate 的代理对象实例
  Calculate calculateProxy = (Calculate) createJDKProxy(target );
  // jdk动态代理对象实例和目标对象实例 同宗同族 ( 他们都实现了相同的接口 )
  System.out.println(calculateProxy instanceof Calculate);
  System.out.println(target instanceof Calculate);

  System.out.println( "代理方法的结果是 : " + calculateProxy.div(100,20) );

  // jdk动态代理创建出来的代理对象实例 是 目标对象 接口的一个实现类
  // 这个代理对象 和 目标对象类没有父子关系 ( 只能用接口接收代理对象 )
 }
}

使用 Cglib 代理

  1. Jdk动态代理是通过实现目标对象所有接口产生一个代理对象实例从而解决问题.
  2. 如果目标对象没有接口.则可以使用Cglib动态代理技术.
  3. Cglib动态代理技术对目标对象有没有实现接口,没有要求.
  4. Cglib动态代理技术,是通过拷贝然后修改目标对象的类的字节码来产生一个代理对象
  5. 而且这个Cglib产生的代理对象实例 是 目标对象的一个子类.

IA 接口 IA.java

public interface IA {
 public String show(String start);
}

IA 实现类 IAImpl.java

public class IAImpl implements IA {
 @Override
 public String show(String start) {
  System.out.println(start + "开始表演!");
  return start + "表演的不错!!";
 }
}

使用 Cglib 代理 CglibProxyFactory.java


public class CglibProxyFactory {

 public static Object createCglibProxy(Object target){
  // 是 Cglib 用于创建代理对象的增强工具类
  Enhancer enhancer = new Enhancer();
  // Cglib需要对目标对象的Class字节码进行修改.
  // Cglib产生的代理对象实例.是目标对象的子类
  enhancer.setSuperclass(target.getClass());
  // 只要是代理都会对原来的内容进行增强操作 ( 增强就是在原有功能上 额外添加的功能 )
  // setCallback() 设置用于增强 操作的实现类( MethodInterceptor对代理方法进行拦截 )
  // 每次只要调用Cglib代理的方法,都会执行 MethodInterceptor 接口中 intercept() 方法
  enhancer.setCallback(new MethodInterceptor() {
   
   @Override
   public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    Object result = null;
    try {
     LogUtils.logBefore(method.getName(), args);
     // 调用目标方法 [加 / 减 / 乘 / 除 / 或具体方法]
     result = method.invoke(target, args);
     // 执行增强代码
     LogUtils.logAfterReturning(method.getName(), args);
    }catch (Exception e){
     e.printStackTrace();
     LogUtils.logAfterThrowing(method.getName(), e);
    }

    return result;
   }
  });
  // 创建 Cglib 代理对象实例
  return enhancer.create();
 }
 //测试
 public static void main(String[] args) {
  // 目标对象
  Calculate calculate = new CalculateImpl();
  // 创建代理对象实例
  Calculate cglibProxy = (Calculate) createCglibProxy(calculate);
  // 调用代理方法式会执行 MethodInterceptor 接口中 intercept() 方法
  int result = cglibProxy.div(120, 0);
  // Cglib 代理 是目标子类执行 MethodInterceptor 接口中 intercept() 方法
  System.out.println(cglibProxy instanceof Calculate);
 }
}

优点:在没有接口的情况下,同样可以实现代理的效果。
缺点:同样需要自己编码实现代理全部过程。

到此这篇关于Java使用JDK与Cglib动态代理技术统一管理日志记录的文章就介绍到这了,更多相关Java动态代理统一管理日志 内容请搜索考高分网以前的文章或继续浏览下面的相关文章希望大家以后多多支持考高分网!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/134211.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号