美文网首页
AOP底层实现:JDK动态代理详解

AOP底层实现:JDK动态代理详解

作者: NisyCoding | 来源:发表于2020-06-10 21:08 被阅读0次

一.创建代理的三要素:

  • 原始对象
  • 额外功能
  • 代理对象和原始对象实现相同的接口

打个比方,我去卖房子,然后我要带客户去看房子;可是有一天,我不想每天都带那么多的客户去看房子,我该怎么办呢?找中介.让中介代替我,领着客户去看房子.那么中介需要伪装成是房东(此时就要重写原始对象中的方法).

二.JDK动态代理:

Proxy.newProxyInstance(classloader,interfaces,invocationHandler)

2.1 invocationHandler介绍:

2.1.1 MethodInterceptor拦截器回顾:

我们在学习spring动态代理之MethodInterceptor拦截器的时候,需要实现MethodInterceptor接口,此时重写了接口中的invoke方法,invoke参数中有一个MethodInvocation,它此时代表额外功能增加的那个原始方法,代码如下:

public class Arroud implements MethodInterceptor {

    /**
     * spring动态代理之MethodInterceptor拦截器
     * @param methodInvocation :额外功能增加的那个原始方法,如:register(),login()
     * @return: 因为每个方法的返回值都不一样,所以需要object类来接受
     * @throws Throwable
     */
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("额外功能----");
        //表示:该原始方法执行了,如register,login方法
        Object proceed = methodInvocation.proceed();
        System.out.println("方法的返回值:object="+proceed);
        return proceed;
    }
}

我们会发现,这个methodInvocation是被spring进行封装了的,但是我们的JDK的代理还是原生的.

2.1.2 InvocationHandler介绍和演示:

invocationHandler是一个接口.我们需要重写invoke方法,从而来增加额外的功能

/**
         * 2.额外功能
         *
         *
         */
        final InvocationHandler invocationHandler=new InvocationHandler() {
            /**
             * 为什么是method.invoke? 因为动态代理. 省去了service.register,service.login()
             *
             * @param proxy 代理对象
             * @param method 原始对象的原始方法
             * @param args  原始方法的参数
             * @return   原始方法的返回值
             * @throws Throwable
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //2.1 新增额外功能
                System.out.println("jdk proxy...");
                //2.2 执行原始对象的原始方法
                Object invoke = method.invoke(userService, args);
                return invoke;
            }
        };

语法糖: jdk1.8之后,我们可以省略掉上面的final修饰符

三. interfaces介绍:

代理创建3要素的第三条,代理对象和原始对象需要实现相同的接口,这里的interfaces就是实现的接口.
此时,我们怎么获取到这个接口呢?通过getClass().getInterfaces()可以获取到类的所有接口定义.

四. classloader介绍:

4.1 类加载器怎么获取呢?

(1).我们知道,一个user.java文件,通过编译成user.class的字节码文件,这里每个类的class文件,自动会分配与之对应的classloader类加载器;
(2).类加载器会把user.class字节码文件放入到JVM虚拟机中;
(3).jvm虚拟机如何去创建一个user对象呢?此时肯定需要拿到user的class对象才能去创建user对象.此时也是通过类加载器去生成Class对象.

此时,问题来了,我现在是动态代理呀,我拿不到具体的.java文件,我也没有具体的.class文件呀,顺其自然的,我也就没有对应的类加载器呀,我该怎么办?
答: 去借一个

五.最终的JDK动态代理代码如下:

package com.baizhiedu.jdl;


import com.baizhiedu.proxy.User;
import com.baizhiedu.proxy.UserService;
import com.baizhiedu.proxy.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JDK动态代理
 */
public class TestJdkProxy {

    public static void main(String[] args) {

        //1.创建原始对象UserService
        final UserService userService = new UserServiceImpl();


        /**
         * 2.额外功能
         *
         *
         */
        final InvocationHandler invocationHandler=new InvocationHandler() {
            /**
             * 为什么是method.invoke? 因为动态代理. 省去了service.register,service.login()
             *
             * @param proxy 代理对象
             * @param method 原始对象的原始方法
             * @param args  原始方法的参数
             * @return   原始方法的返回值
             * @throws Throwable
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //2.1 新增额外功能
                System.out.println("jdk proxy...");
                //2.2 执行原始对象的原始方法
                Object invoke = method.invoke(userService, args);
                return invoke;
            }
        };

        /**
         * 3.代理对象和原始对象实现相同的接口  interfaces:原始对象所实现的接口
         * 先借用userService的classLoader TestJdkProxy也可以
         */

        UserService service = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler);
        service.login(new User());
        service.register("Nisy",20);
    }
}

5.1 运行结果:

jdk proxy...
登录功能的核心代码...
jdk proxy...
注册功能的核心代码...

相关文章

  • 2018-09-16

    AOP的XML配置: AOP的先关术语: Spring底层的AOP实现原理 动态代理: JDK动态代理:只能对实现...

  • 3.3AOP简介-第3章aop面向切面编程

    AOP:面向切面编程,底层采用动态代理实现的,采用了两种代理:jdk的动态代理与CGLIB的动态代理。AOP是动态...

  • SSH框架之Spring进阶AOP面向切面编程(三)

    第一节:AOP简介 第二节:AOP的作用 第三节:Spring底层的AOP实现原理 动态代理: JDK动态代理:只...

  • AOP底层实现:JDK动态代理详解

    一.创建代理的三要素: 原始对象 额外功能 代理对象和原始对象实现相同的接口 打个比方,我去卖房子,然后我要带客户...

  • AOP底层实现

    AOP底层实现 Spring在运行期,生成动态代理对象,不需要特殊的编辑器 Sping AOP的底层就是通过JDK...

  • 细说Spring——AOP详解(使用CGLIB实现AOP)

    一、动态代理实现AOP的缺陷 在上一篇文章细说Spring——AOP详解(动态代理实现AOP)中讲解了如何使用动态...

  • Spring之使用XML配置Spring AOP

    1.aop的原理 Spring AOP底层主要使用了JDK动态代理和cglib动态代理。具体可看文章设计模式之代理...

  • Spring AOP详解

    AOP AOP的实现一般都是基于 代理模式 ,在JAVA中采用JDK动态代理模式,但是我们都知道,JDK动态代理模...

  • springboot aop

    springboot怎样使用aop呢?我们知道aop的实现一种是jdk动态代理实现aop,一种是cglib动态代理...

  • Spring AOP DefaultAdvisorAutoPro

    Spring AOP源码目录 Spring AOP源码01:Jdk动态代理底层源码Spring AOP源码02:P...

网友评论

      本文标题:AOP底层实现:JDK动态代理详解

      本文链接:https://www.haomeiwen.com/subject/ztcmtktx.html