代理-动态代理(jdk自带)

发表于 2016-09-20 01:28 显示全部楼层 16 2756

本帖最后由 叶星飞 于 2016-9-20 19:25 编辑

前一篇代理-概念与代理模式(静态)讲了代理的概念及代理模式,这一篇讲java中动态代理。

讲之前先来科普一下(网上普遍认可的定义):

静态代理:

  由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。


动态代理:

  动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。


  又懵逼了吧,大白话讲,静态代理就是 代理类(C同学)跟委托类(A同学)间的关系是固定的,程序运行前,代理类跟委托类已经以.class文件形式存在硬盘里。而动态代理则是,根据需求,决定是否需要创建代理类,需要时,在jvm内存中动态拼接出一份.class文件,而这个.class文件就是代理类,仅存在内存中,程序结束后便销毁。


还是用回上篇的例子:

       A同学 喜欢 B同学,想送花,送小礼物给她,但是太过于羞涩,让C同学代替送了。之后,每逢年过节,鲜花,礼物什么的C同学很乐意代劳,最后的最后,B 同学跟C同学可耻的在一起了。

blob.png

A同学负责送花,送礼物,B同学负责收花,收礼物,C同学是第三方,仅起到中间媒介的作用。


换成动态代理实现(JDK自带的):

思路:

1、创建送礼物,送花代理动作接口

2、创建真实对象(委托类),实现代理动作接口

3、实现InvocationHandler接口,重写invoke方法,自定义代理方法处理策略 

4、通过Proxy.newProxyInstance方法获取代理对象

5、代理对象执行方法

//代理动作
public interface Giving  {
	public void giveFlower();
	
	public void giveGift();
}
//真实对象
public class StudentA implements Giving{
	@Override
	public void giveFlower() {
		System.out.println("送花...");
	}

	@Override
	public void giveGift() {
		System.out.println("送礼物...");
	}
}
//接受方(酱油角色)
public class StudentB {

}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理对象生成、操作的类
public class GivingInvocationHandler implements InvocationHandler{
	//处于通用性的考虑,使用Object
	private Object realObject; //真实对象(A同学)
	private Object targetObject; //目标对象(B同学)
	public GivingInvocationHandler(Object realObject,  Object targetObject){
		this.realObject = realObject;
		this.targetObject = targetObject;
	}
	//生成的代理对象(C同学)
	public <T> T getProxyInstance(){
		/**
		 * 参数1:类加载器
		 * 参数2:真实对象实现的接口集合(Giving接口)
		 * 参数3:InvocationHandler接口 实现类,用于回调
		 */
		return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), 
				realObject.getClass().getInterfaces(), this);
	}
	/**
	 * 参数1:代理对象
	 * 参数2:代理动作包装对象
	 * 参数3:动作的执行参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
		System.out.print("C代A同学给B同学:");
		//此处通过反射获取执行这是对象的方法
		return method.invoke(realObject, params);
	}
}
//测试类
public class App {
	public static void main(String[] args) {
		StudentA studentA = new StudentA();
		StudentB studentB = new StudentB();
		
		GivingInvocationHandler handler = new GivingInvocationHandler(studentA, studentB);
		
		Giving proxy = handler.getProxyInstance();
		
		proxy.giveFlower();
		proxy.giveGift();
	}
}	


总结:

静态代理

优点:

  具有代理共有的优点,相对动态代理,静态代理逻辑简单,操作方便。

缺点:

   1、业务类(委托方)与代理类需要共同实现一个接口,每个方法独立代理,如果业务类拥有较多方法时,代理也随之增加,不如动态代理统一在invoke方法中处理。(可以对GivingInvocationHandler进行通用化改造) 

   2、业务类(委托方)添加方法或其他操作之后,代理类也必须对应添加,代码维护相当麻烦。


动态代理:

优点: 

   动态代理出现,弥补了静态代理中的缺点,业务类所有方法,都统一到一个处理器(InvocationHandler.invoke)中处理,而代理类仅需要操做处理器便可以实现代理。

缺点: 

  java jdk自带的动态代理机制只能对实现接口的业务类进行代理,无法对普通类进行代理,刚好cglib的出现,又弥补的这个缺陷。

   

注意:此篇仅介绍如何使用JDK自带的动态代理,至于实现原理,敬请期待下篇。




回复 使用道具
举报
目定口呆

发表于 2017-02-10 03:56 显示全部楼层

祝愿小码哥越来越红火!!红红火火恍恍惚惚!

回复 支持 反对 使用道具
举报
宁静致远

发表于 2017-02-10 03:54 显示全部楼层

回复 支持 反对 使用道具
举报
宁静致远

发表于 2017-02-09 05:35 显示全部楼层

回复 支持 反对 使用道具
举报
谁和我同名

发表于 2017-02-09 05:28 显示全部楼层

回复 支持 反对 使用道具
举报
艇仔饭

发表于 2017-02-09 02:32 显示全部楼层

回复 支持 反对 使用道具
举报
陈小呆

发表于 2017-02-09 01:43 显示全部楼层

前排支持!!

回复 支持 反对 使用道具
举报
凉月流沐

发表于 2017-02-08 22:14 显示全部楼层

每一个成功者都有一个开始。成功的路,始于回复。

回复 支持 反对 使用道具
举报
cocoabird

发表于 2017-02-08 19:44 显示全部楼层

回复 支持 反对 使用道具
举报
12下一页

发表新文章
叶星飞

叩丁狼骨干成员

0

学分

982

学币

1035

积分

叩丁狼骨干成员

Rank: 6Rank: 6

积分
1035
Ta的主页 发消息
精华帖排行榜

精彩推荐

  • 关注叩丁狼教育