Java Proxy初解

Java Proxy初解

前言

动态代理提供了一种灵活且非侵入式的方式,可以对对象的行为进行定制和扩展。它在代码重用、解耦和业务逻辑分离、性能优化以及系统架构中起到了重要的作用。

增强对象的功能:通过动态代理,可以在不修改原始对象的情况下,对其方法进行增强或添加额外的行为。可以在方法执行前后进行一些操作,比如日志记录、性能监测、事务管理等。

解耦和业务逻辑分离:动态代理可以将对象的特定操作从业务逻辑中解耦,使得代码更加模块化和可维护。代理对象可以负责处理一些通用的横切关注点,而业务对象可以专注于核心业务逻辑。

实现懒加载:通过动态代理,可以延迟加载对象,只有在真正需要使用对象时才会进行创建和初始化,从而提高性能和资源利用效率。

实现远程方法调用:动态代理可以用于实现远程方法调用(RPC)和分布式系统中的服务代理。客户端通过代理对象调用远程服务,并隐藏了底层网络通信的细节。

实现AOP编程:动态代理是实现面向切面编程(AOP)的基础。通过代理对象,可以将横切关注点(如日志、事务、安全性)与业务逻辑进行解耦,提供更高层次的模块化和可重用性。

使用

java的动态代理只能代理接口的方法

//实现 InvocationHandler 接口 此接口是增强方法功能的
public class MyInvocationHandler implements InvocationHandler {

  private Object target;

  public MyInvocationHandler(Object target) {
    this.target = target;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("查询参数" + args[0]);
    System.out.println("执行方法" + method.getName());
    return method.invoke(target, args);
  }

}
	//创建一个接口对象
    UserService userService = new UserServiceImpl();
	//创建了实现了InvocationHandler接口的对象 将要代理的对象放进去
    MyInvocationHandler handler = new MyInvocationHandler(userService);
	//调用Proxy.newProxyInstance方法生成代理对象
    UserService o = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), 		                           userService.getClass().getInterfaces(), handler);
	//代理对象调用接口里的方法
    System.out.println(o.getUserByName("admin"));
    // o为java.lang.reflect.Proxy 的子类
    System.out.println(o.getClass().getSuperclass().getName());
	// 代理类名称
    System.out.println(o.getClass().getName());

	//打印的数据
	//查询参数admin
    //执行方法getUserByName
    //User [id=null, username=null, user_name=admin]
    //java.lang.reflect.Proxy
    //com.sun.proxy.$Proxy0

源码解析

    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);
		//克隆需要实现的接口列表
        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         * 生成一个代理类对象	
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
			//根据生成的代理类对象获取含有InvocationHandler类型参数的构造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            //构造一个代理类对象
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

	//含有InvocationHandler参数的构造方法为父类的proxy的构造方法
	protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }
	//constructorParams为
    private static final Class<?>[] constructorParams = { InvocationHandler.class };
		

生成代理类对象

    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        //校验接口数量
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        //缓存获取
        return proxyClassCache.get(loader, interfaces);
    }

	//proxyClassCache 具体实现在 ProxyClassFactory中 
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());


	
	//获取代理类对象的工厂 根据一个类加载器、接口数组获取一个类对象
    private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
        // prefix for all proxy class names 代理类对象的名称类前缀
        private static final String proxyClassNamePrefix = "$Proxy";

        // next number to use for generation of unique proxy class names 下一个代理类名称序号
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
			//IdentityHashMap使用 == 来判断key是否相同
            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            //遍历接口列表
            for (Class<?> intf : interfaces) {
                /*
                 * Verify that the class loader resolves the name of this
                 * interface to the same Class object.
                 */
                Class<?> interfaceClass = null;
                try {	
                    //使用类加载器去加载对应的接口
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                //如果加载的接口类不是一个 则抛出异常 类加载器不对
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.
                 */
                //不是接口则抛出异常
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.
                 */
                //校验重复的接口
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }
			//代理类所在包
            String proxyPkg = null;     // package to define proxy class in
            //访问权限
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.
             */
            //判断代理类需要放在哪个包下
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
                //如果解口不是Public的需要将代理类放在和接口同一包下
                if (!Modifier.isPublic(flags)) {
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    //获取包名
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        //多个不是Public的接口在不同包 抛出异常
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                //默认的代理类包
                // public static final String PROXY_PACKAGE = "com.sun.proxy";
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * Choose a name for the proxy class to generate.
             */
            long num = nextUniqueNumber.getAndIncrement();
            //生成代理类名称
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*
             * Generate the specified proxy class.
             */
            //生成代理类的字节码数据
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                //根据字节码获取代理类的Class对象
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

总结

  1. 代理类对象是Proxy的子类
  2. 代理类对象实现了给定的接口
  3. 代理类对象在调方法时调用的InvocationHandler接口的invoke方法

流程

  1. 根据接口信息、访问权限、代理名称生成对应类的字节码信息
  2. 根据字节码信息和类加载器生成对应类的Class对象
  3. 根据Class对象创建含有InvocationHandler类型的构造方法
  4. 根据构造方法和传进来的InvocationHandler构造一个对象
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值