动态代理 (JDK 动态代理)

动态代理 代理类在程序运行时被创建,这种代理方式称为动态代理

动态代理实现有两种方式,JDK 动态代理和 CGlib 动态代理,本文介绍JDK 动态代理

JDK 动态代理:创建动态代理类,实现 InvocationHandler 接口,重写 invoke 方法,在 invoke 方法中通过反射调用被代理类的方法,实现代理。jdk 动态代理只能代理接口,即只能代理接口的实现类

 

JDK 动态代理示例代码

定义一个接口

package com.jdkdynamicproxy.service;

public interface Subject {
	
	void proxyMethod();

}

被代理类,实现接口

package com.jdkdynamicproxy.service.impl;

import com.jdkdynamicproxy.service.Subject;

/**
 * 被代理类
* @author Administrator
*/
public class AgentTarget implements Subject {

	@Override
	public void proxyMethod() {
		System.out.println("被代理的方法执行了");
	}
}

 动态代理类,实现 InvocationHandler 接口

package com.jdkdynamicproxy.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.jdkdynamicproxy.service.impl.AgentTarget;

/**
   * 动态代理类,实现 InvocationHandler接口
 * @author Administrator
 */
public class JdkDynamicProxySubject implements InvocationHandler {
	
	private AgentTarget agentTarget;

	public JdkDynamicProxySubject(AgentTarget agentTarget) {
		this.agentTarget = agentTarget;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		    //动态代理逻辑
            System.out.println("before");
            Object res = null;
            try {
        	     //用反射调用被代理类的方法
                 res = method.invoke(agentTarget, args);
            }catch (Exception ex){
                System.out.println("ex:" + ex.getMessage());
                throw ex;
            }finally {
                System.out.println("after");
            }
            return res;
	}
}

测试类

package com.jdkdynamicproxy;

import java.lang.reflect.Proxy;
import com.jdkdynamicproxy.jdkproxy.JdkDynamicProxySubject;
import com.jdkdynamicproxy.service.Subject;
import com.jdkdynamicproxy.service.impl.AgentTarget;

public class JdkDynamicProxyMain {

	public static void main(String[] args) {
		
	      //配置系统属性sun.misc.ProxyGenerator.saveGeneratedFile为true,代理类生成时会自动将生成的代理类写入硬盘
              System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

              Subject subject = (Subject) Proxy.newProxyInstance(
    		          JdkDynamicProxyMain.class.getClassLoader(), //类加载器
                          new Class[]{Subject.class} ,  //代理接口
                          new JdkDynamicProxySubject(new AgentTarget()) //InvocationHandler对象
              );
      
              subject.proxyMethod();
	}
}

运行如下

程序运行后,在项目目录下生成了代理类的 class 文件

对生成的 $Proxy0.class 文件进行反编译

package com.sun.proxy;

import com.jdkdynamicproxy.service.Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Subject {
	private static Method m1;
	private static Method m2;
	private static Method m3;
	private static Method m0;

	public $Proxy0(InvocationHandler var1) throws  {
      super(var1);
   }

	public final boolean equals(Object var1) throws  {
      try {
         return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
      } catch (RuntimeException | Error var3) {
         throw var3;
      } catch (Throwable var4) {
         throw new UndeclaredThrowableException(var4);
      }
   }

	public final String toString() throws  {
      try {
         return (String)super.h.invoke(this, m2, (Object[])null);
      } catch (RuntimeException | Error var2) {
         throw var2;
      } catch (Throwable var3) {
         throw new UndeclaredThrowableException(var3);
      }
   }

	public final void proxyMethod() throws  {
      try {
         super.h.invoke(this, m3, (Object[])null);
      } catch (RuntimeException | Error var2) {
         throw var2;
      } catch (Throwable var3) {
         throw new UndeclaredThrowableException(var3);
      }
   }

	public final int hashCode() throws  {
      try {
         return (Integer)super.h.invoke(this, m0, (Object[])null);
      } catch (RuntimeException | Error var2) {
         throw var2;
      } catch (Throwable var3) {
         throw new UndeclaredThrowableException(var3);
      }
   }

	static {
		try {
			m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
			m2 = Class.forName("java.lang.Object").getMethod("toString");
			m3 = Class.forName("com.jdkdynamicproxy.service.Subject").getMethod("proxyMethod");
			m0 = Class.forName("java.lang.Object").getMethod("hashCode");
		} catch (NoSuchMethodException var2) {
			throw new NoSuchMethodError(var2.getMessage());
		} catch (ClassNotFoundException var3) {
			throw new NoClassDefFoundError(var3.getMessage());
		}
	}
}

可以看到生成的 $Proxy0.class 实现了 Subject 接口,重写 proxyMethod 方法。在重写的 proxyMethod 方法中,去调用 JdkDynamicProxySubject 的 invoke(Object proxy, Method method, Object[] args) 方法,实现代理

 

整个程序的运行流程:Proxy.newProxyInstance(JdkDynamicProxyMain.class.getClassLoader(), new Class[]{Subject.class} , new JdkDynamicProxySubject(new AgentTarget()) )  创建对象 subject 时,生成了代理类 $Proxy0.class;subject 对象调用proxyMethod 方法时,proxyMethod 方法调用 JdkDynamicProxySubject 的 invoke 方法,invoke 方法中通过反射调用被代理方法,实现动态代理

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟世君子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值