JDK动态代理学习笔记

原创 2018年04月17日 18:13:47

一、代理的认识

    在信息不发达的年代总有人被其他人冒名顶替,上完大学,参加工作,而被顶替的人根本不知道,周边的人也不能发现出现冒名顶替了。因此为了做到替换别人且不被发现,因此冒名者需要熟悉被顶替人的一切方法,属性。当然冒名者也有自己的一些特有方法,属性。
    我对代理模式额认识也是这样的。首先,为了混人耳目,与真实对象一致,因此代理对象内部一般需要封装真实对象,用于完成对真实对象方法的调用。这和装饰模式有点类似。

二、动态代理模式的实现思想

    冒名顶替的实现:在现实生活中,冒名顶替者一般需要把自己的一切信息都改成被顶替者,自己的姓名,年龄,经历,以及家庭关系。
     代理的实现:与冒名顶替的实现基本一致,首先需要有个冒名顶替这,也就是制造一个新的类。同时这个冒名顶替者把所有信息以及关系都改成和被顶替者一致,也就是新制造的这个类需要实现了真实对象所实现的接口,从而在外看看起来是同一对象。

三、JDK动态代理工具

    既然是偷偷冒名顶替别人,那么我们需要确定两件事:
    1、我们要顶替谁,也就是我们需要对哪个真实对象生成代理对象

    2、为什么我们要顶替他。当然是为了,在他的方法执行前,执行后我们可以做一些手脚。

有了这两个目的,那么需要一个接口 invocationhandler(interface)和一个类proxy(class)来帮助我们。

    1、proxy类帮助我们冒名顶替,帮助我们生成代理对象。
Proxy类中有一个静态方法NewProxyInstance(loader, interfaces, h),他可以帮助我们生成代理对象,这里有三个参数,第一个参数classloader是指真实对象的类加载器,第二个参数interface是指真实对象的类所实现的口数组,第三个参数h是invocationhandler,是代理真实对象的调用处理器。
    2、invocationhandler(interface) 这接口中只有一个方法invok();这个方法就是我们要替换真实对象的方法,当代理对象调用方法时,都会进入invoke()方法中,因此我们可以在invoke()方法中加入自己需要的功能。

四、JDK动态代理的具体使用

    由上我们知道真实对象所在的类必须实现某些接口,因此在这里我们给一个IUser接口,该接口中只有一个say()方法

public interface IUser {
 void say();
}

然后在写个User类实现该接口,我们就对User实例对象进行代理

public class User implements IUser {
@Override
public void say() {
  System.out.println("真实对象方法正在执行中");
}
}

对象准备完成后,我们准备对User类的实例对象进行代理。代理分为两部分,1、生成代理对象。2、invoke()方法override
public class MyProxy implements InvocationHandler {
 private Object user =null;
 /*
  * 自定义一个方法将user对象传入
  * 通过Proxy类生成代理对象
  * 方法返回值为一个objcet的代理对象
  * 
  */
 public Object getProxy(Object user) {
  this.user=user;
  return Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), this);
 }
 /*
  * Override invoke()方法
  * 
  */
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  System.out.println("代理方法正在运行");
  System.out.println("调用真实对象方法之前");
  Object object = method.invoke(user, args);
  System.out.println("调用真实对象方法之后");
  return object;
 }
}

invoke()方法中三个参数详解,第一个参数Object proxy,是指代理对象。第二个参数是当前调用方法中的实例对象,在本例中指say()方法。第三个参数Object[] args,是method中的参数数组。


完成代理对象的生成,和逻辑方法的覆写后,测试一下
public void tset() {
  MyProxy myProxy = new MyProxy();
  
  IUser proxy_1 = (IUser)myProxy.getProxy(new User());
  
  proxy_1.say();
 } 

千万注意:代理对象是挂靠在真实对象所在类实现的某个接口上的,所以,在对代理对象强制类型转换时一定是接口。

 IUser proxy_1 = (IUser)myProxy.getProxy(new User());

执行结果如下:

代理方法正在运行
调用真实对象方法之前
真实对象方法正在执行中
调用真实对象方法之后

可见,代理对象调用say()方法,实际上是调用了invoke()方法。完成对user对象的代理

五、CGLIB动态代理

1、CGLIB动态代理认识

有时候我们找不到接口,不能由JDK动态代理生成一个接口对象,这时,我们提供另外一种不需要接口的动态代理方法CGLIB动态代理。CGLIB动态代理的核心是生成一个真实对象子类的代理对象。

2、动态代理具体实例
(1)准备真实对象

public class User {

	public void say() {
		System.out.println("真实对象方法正在执行中");
	}
}

(2)生成子类代理对象

public class ProxyFactory implements MethodInterceptor {
	//目标对象
	private Object target;
	
	public ProxyFactory(Object target) {
		this.target = target;
	}


	//生成代理对象
	public Object getProxyInstance()
	{
		//工具对象
		Enhancer enhancer = new Enhancer();
		//设置父类
		enhancer.setSuperclass(target.getClass());
		//设置回调函数,执行target方法时会出发拦截方法interceptor()
		enhancer.setCallback(this);
		//创建代理对象
		return enhancer.create();
		
	}
	
	@Override
	public Object intercept(Object object, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
		
		System.out.println("事物开启");
		//真实对象方法调用
		Object resultObjcet = method.invoke(target, arg);
		
		System.out.println("事物结束");
		
		return resultObjcet;
	}
}

(3)测试类

@Test
	public void proxyTest() {
		User user = new User();
		User obj = (User)new ProxyFactory(user).getProxyInstance();
		obj.say();
	}

(4)测试结果

事物开启
真实对象方法正在执行中
事物结束
使用CBLIB动态代理,需要使用enhancer工具对象,通过该对象setSuperClass方法将真实对象所在类设置为父类,通过setCallBanck方法,设置回调函数,也就是当需要执行真实对象方法时会触发interceptor方法执行。

Java新特性--Java Web Start

 JavaTM Web Start文档目录 JD018 cherami cherami@163.net JavaTM Web Start 1.01版和Java 2 SDK 及Java 2运行时环境(J...
  • cherami
  • cherami
  • 2001-09-30 10:29:00
  • 1150

jdk动态代理学习笔记

  • 2013年03月06日 11:10
  • 82KB
  • 下载

JDK动态代理_JDK动态代理

  • 2009年10月18日 10:56
  • 32KB
  • 下载

JDK动态代理示例

Java动态代理可以动态地创建代理并动态地处理对所代理方法的调用。下面用《Java编程思想》中的一个例子说明: 首先是接口类,目标类要实现的接口:public interface Interface...
  • x_i_y_u_e
  • x_i_y_u_e
  • 2016-04-29 21:08:02
  • 1069

jdk动态代理示例以及代码原理分析

相信很多人在刚刚学习Java时,会感觉【动态代理】晦涩难懂,只知道如何来调用它,却不知道它的实现细节。本文通过根据JDK源码,展示这些细节,以期能对JDK的动态代理有深入的理解。 简单示例代码 pub...
  • PKWind
  • PKWind
  • 2016-12-09 14:49:21
  • 1079

jdk动态代理例子

jdk动态代理例子1. 声明接口package cn.zhengyong.proxy;/** * 接口 * @author zhengyong * */ public interface Or...
  • zhengyong15984285623
  • zhengyong15984285623
  • 2016-06-17 15:26:08
  • 873

Java JDK 动态代理(AOP)使用及实现原理分析

一、什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理...
  • xunzaosiyecao
  • xunzaosiyecao
  • 2016-08-07 20:17:08
  • 16173

细说JDK动态代理的实现原理

关于JDK的动态代理,最为人熟知的可能要数Spring AOP的实现,默认情况下,Spring AOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的代理使用CGLIB来实现。那么,什...
  • mhmyqn
  • mhmyqn
  • 2015-09-15 21:12:35
  • 25076

JDK动态代理的实现和原理解析(基于JDK1.7)

一、什么是代理代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。详细介绍请参考:...
  • xiaokang123456kao
  • xiaokang123456kao
  • 2017-08-29 20:18:17
  • 1339

CGLIB 和 JDK生成动态代理类的区别

AOP 使用的设计模式就是代理模式,是对IOC设计的补充。为了扩展性,往往会加上反射,动态生成字节码,生成代理类。  这里往往还会使用到DI,把代理的实现类通过依赖注入的方式,传给代理工厂。  关于生...
  • hanxuemin12345
  • hanxuemin12345
  • 2014-10-31 00:19:53
  • 7015
收藏助手
不良信息举报
您举报文章:JDK动态代理学习笔记
举报原因:
原因补充:

(最多只允许输入30个字)