• Java动态代理详解


    目前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方法的说明:

    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");
        }
    
    }
    

    输出:

    --------------begin-------------
    hello  world
    --------------end-------------
    

    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;
        }
    }
    

    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的原理。

    转自 java动态代理详解

  • 相关阅读:
    完全背包
    01背包
    游戏编程:为什么C++游戏开发比Java更好,其实是因为这两个点!
    VS code搭建 C 和 C++ 环境的完整图文教程!赶紧收藏,这波不亏!
    来自清华计算机系的招聘信息,第一个要求就劝退99%的人!网友:但福利待遇真好!
    C++ 必看书籍清单!从C++ Primer 到 源码剖析,精通真的很难!
    C语言简单编程速成!保姆级入门教程, 目标达成!
    9 名程序员被抓!这次是真的活该.....
    你知道各类开发语言的薪酬差距吗?高薪在于适合,而不在于广度!
    apache common包 CollectionUtils 使用 详解
  • 原文地址:https://www.cnblogs.com/Fzeng/p/14691415.html
Copyright © 2020-2023  润新知