>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 23733 个阅读者 刷新本主题
 * 贴子主题:  java动态代理详解 回复文章 点赞(0)  收藏  
作者:日月光华    发表时间:2019-11-17 15:34:20     消息  查看  搜索  好友  邮件  复制  引用

java动态代理详解

版权声明:本文遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文转自:https://blog.csdn.net/qq_32532321/article/details/81874990

目前java动态代理的实现分为两种

1.基于JDK的动态代理
2.基于CGILB的动态代理
在业务中使用动态代理,一般是为了给需要实现的方法添加预处理或者添加后续操作,但是不干预实现类的正常业务,把一些基本业务和主要的业务逻辑分离。我们一般所熟知的Spring的AOP原理就是基于动态代理实现的。

1.基于JDK的动态代理

基于JDK的动态代理就需要知道两个类:1.InvocationHandler(接口)、2.Proxy(类)
还要知道JDK是基于接口的动态代理
下面我们实际用代码来讲解这两个类的实际作用

1.第一步,创建一个接口
public interface Subject {
    void hello(String param);
}

2.第二步,实现接口


public class SubjectImpl implements Subject {
    @Override
    public void hello(String param) {
        System.out.println("hello  " + param);
    }
}

3.第三步,创建SubjectImpl的代理类


public class SubjectProxy implements InvocationHandler {
    private Subject subject;

    public SubjectProxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("--------------begin-------------");
        Object invoke = method.invoke(subject, args);
        System.out.println("--------------end-------------");
        return invoke;
    }
}

invoke方法的说明:
点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小
4.编写代理类实际的调用,利用Proxy类创建代理之后的Subject类。


public class Main {

    public static void main(String[] args) {
        Subject subject = new SubjectImpl();
        InvocationHandler subjectProxy = new SubjectProxy(subject);
        Subject proxyInstance = (Subject) Proxy.newProxyInstance(subjectProxy.getClass().getClassLoader(), subject.getClass().getInterfaces(), subjectProxy);
        proxyInstance.hello("world");
    }

}

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小
输出:
--------------begin-------------
hello  world
--------------end-------------
看这个结果,实际上在Subject类中只会输出一条hello world,但是在被代理之后,实际调用的方法是SubjectProxy的invoke方法,这样可以在不修改业务类的情况下对业务类增加一些日志等其他操作,甚至可以直接修改有返回值方法的返回值。

2.基于CGLIB的动态代理

本文主要讲的是CGLIB的动态代理,因为基于JDK的动态代理一定要继承一个接口,而绝大部分情况是基于POJO类的动态代理,那么CGLIB就是一个很好的选择,在Hibernate框架中PO的字节码生产工作就是靠CGLIB来完成的。还是先看代码。

1.引入CGLIB的jar包
2.创建代理类


public class CGsubject {
    public void sayHello(){
        System.out.println("hello world");
    }
}

如果直接对这个类创建对象,那么调用sayHello方法,控制台就会输出hello world,现在我们还是要对输出添加前置和后置的log输出。来打印输出前和输出后的时间。

3.实现MethodInterceptor接口,对方法进行拦截处理。


public class HelloInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("begin time -----> "+ System.currentTimeMillis());
        Object o1 = methodProxy.invokeSuper(o, objects);
        System.out.println("end time -----> "+ System.currentTimeMillis());
        return o1;
    }
}

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小
4.创建被代理类


public class Main {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(CGsubject.class);
        enhancer.setCallback(new HelloInterceptor());
        CGsubject cGsubject = (CGsubject) enhancer.create();
        cGsubject.sayHello();
    }

}

利用Enhancer来生产被代理类,这样可以拦截方法,对方法进行前置和后置log的添加。
输出:
begin time -----> 1534836443741
hello world
end time -----> 1534836443786
这样普通的java类也能被代理。后续会分析CGLIB的原理。



程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->输入与输出(上)
  JavaWeb开发-->JSP中使用JavaBean(Ⅰ)
  JSP与Hibernate开发-->Spring、JPA与Hibernate的整合
  Java网络编程-->安全网络通信
  精通Spring-->创建综合购物网站应用
  Vue3开发-->通过Vuex进行状态管理
  解决javac编译错误: 编码UTF8/GBK的不可映射字符
  Java集合框架学习---深入探究ArrayList源码
  Java函数式接口和Stream流
  Java并发编程的总结与思考
  使用 RocketMQ 事务消息,实现分布事务
  Java设计模式中的工厂模式和策略模式范例
  Java方法的嵌套与递归调用
  深入研究java.lang.ThreadLocal类
  java常见的几种调用机制:同步调用,异步调用,回调
  Java 入门实用代码: 数组差集
  Java入门实用代码: 字符串格式化
  通过java.net.URL类连接HTTP服务器时获取响应结果的头部信息
  通过Java读取Excel数据
  中国有多少程序员?现在还值得学java吗?
  初学者该学哪种编程语言
  更多...
 IPIP: 已设置保密
楼主      
1页 1条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。