初识Java动态代理JDK代理

初识Java动态代理—JDK代理

代理设计模式的三要素:

  1. 有原始类
  2. 额外的方法
  3. 和原始类实现相同的方法

那么就针对上面三个要求分析和实现动态代理

1.newProxyInstance

newProxyInstance是JDK为我们提供的类,用于创建动态代理对象,参数为

Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)                                      
  • ClassLoader loader 是类加载器
  • Class<?>[] interfaces 是原始实现的接口
  • InvocationHandler h 额外方法的实现

那从以上入手

1.获得原始类

原始类很容易获得,通过最简单的new即可例如:

UserService userService =new UserServiceImplNew();

2.和原始类实现相同的接口 interfaces

在上面我们创建出来了userService对象,那么就可以使用class提供的方法获得userService的接口,例如:

userService.getClass().getInterfaces()

3.和原始类实现相同的方法 InvocationHandler

这个将在下面的InvocationHandler中分析

4.类加载器 ClassLoader

  • 普通的创建出对象的流程是:

从Java文件到字节码文件,字节码通过ClassLoader(CL)加载到JVM中,从而我们可以把对象创建出来

  • 而对于动态代理的方法有所不同

代理对象创建我们并没有new它,或者创建它,那么JVM如何获得代理对象的呢?

JDK提供的动态代理方法有创建字节码的的技术,从interfaces 和InvocationHandler传入的接口信息和方法信息就可以实现出一个代理类

然后用JDK提供的动态代理方法创建出动态字节码

最后使用一个CL加载到JVM中

那么如何实现它呢?

在创建userService时JVM为它的字节码加载设置了一个CL,所以我们可以使用这个CL,也可以称作借用

userService.class.getClassLoader()

2.InvocationHandler

​ 首先实现InvocationHandler接口(ideal自动生成)

​ 该接口实现了一个内部类,我们关注的是invoke方法

  InvocationHandler handler=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        };

对于Object invoke(Object proxy, Method method, Object[] args)

  • Object proxy 是代理的对象
  • Method method 是被代理的对象
  • Object[] args 是被代理的对象的参数

​ 前面提到和原始类实现相同的方法,那么怎么实现?

	method.invoke(userService,args);

在Object invoke(Object obj, Object... args) 传入想被代理的对象和args即可,它就代表的原始对象,将被执行

现在添加额外功能

详细实现如下

InvocationHandler handler=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("JDKModle.invoke");
                Object ret= method.invoke(userService,args);
                return  ret;
            }
        };

3.使用代理对象

 UserService userServiceProxy= (UserService) Proxy.newProxyInstance(JDKModle.class.getClassLoader(),userService.getClass().getInterfaces(),handler);

和实现接口一样,只需要代从newProxyInstance得到对象即可

现在把所有代码组装起来

对于下面三个类具体实现,不用关心具体内容,只需要认识方法名字就好

org.User;
org.UserService;
org.UserServiceImplNew;

User


public class User  {
    private String name;
    private String password;
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

UserService

public interface UserService {
    public void register(User user);
    public void login(String name, String password);
}

UserServiceImplNew

public class UserServiceImplNew implements UserService {
    @Override
    public void register(User user) {
        System.out.println("UserServiceImplNew.register");
    }
    @Override
    public void login(String name, String password) {
        System.out.println("UserServiceImplNew.login");
    }
}
package org.PoxyModle;

import org.User;
import org.UserService;
import org.UserServiceImplNew;

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

public class JDKModle {
    public static void main(String[] args) {
        final UserService userService =new UserServiceImplNew();

        InvocationHandler handler=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("JDKModle.invoke");
                Object ret= method.invoke(userService,args);
                return  ret;
            }
        };


        UserService userServiceProxy= (UserService) Proxy.newProxyInstance(JDKModle.class.getClassLoader(),userService.getClass().getInterfaces(),handler);

        userServiceProxy.login("SY","1123");
        userServiceProxy.register(new User());
    }
}

运行如下

image-20210531181504935

3.总结:

JDK动态代理和Spring的动态代理就是一个意思,只不过对JDK封装了,使得更容易使用,了解JDK动态代理对理解AOP编程有好处

newProxyInstance InvocationHandler相互配合才能完成代理操作

初步分析和实现到此为止

posted on 2021-05-31 18:16  NathenJames  阅读(125)  评论(0编辑  收藏  举报