`

总结一下反射的一个应用--动态代理

 
阅读更多

      把《Java核心技术》与《Java编程思想》翻过去。反射一部分讲的大同小异。总体来说《Java核心技术》讲得比较拖沓,但是比较全面,《Java编程思想》讲得比较简略,第一遍看可能看不懂。

      因为之前有仔细研究过几个框架中XML配置文件的语法,发现反射中代理类的应用在框架中虽然是透明的,但是我依然能够感受它的存在。我甚至怀疑AOP的对象不是由编译器生成合成对象实现的,而是由代理对象实现的,因为面向接口编程的思想到处都是。

 

     一、 什么是代理类。

 

     现实中不可能为每个接口都准备好一个适配器类,毕竟Java并不支持多基类继承。有时候我们可能需要动态地生成一个对象,它的内部实现只是对某些方法的一个封装。通过这些封装我们可以实现AOP,比如在某个类的方法执行前、执行后写日志等等。它包含一个类加载器、一些接口列表和一个调用处理器类。

 

     一句话来讲,代理类就是在接口和接口实现类之间加上一个中间层,实现一些中间层特有的操作。

 

 

     二、如何构造一个调用处理器类?

 

 

    1 代理类必须实现InvocationHandler接口,幸运的是,我们只需要重写它的一个抽象方法--Invoke()。

 

    2 这个代理类中必须有一个局部动态代理对象--注意区分,代理处理类中还自带一个局部动态代理对象。这一般可以通过构造器获得。

 

    3 Invoke方法的写法:

        参数1 proxy对象。

        参数2 一个method对象--这是一个高阶函数式的写法。

        参数3 一个arg数组。

 

        必须抛出Throwable类型的异常。

 

 

        函数体内:

 

         (1) 加入自己想要的内容。

         (2) return method.invoke(proxy,args)。即使用反射的方法确实地执行这个方法method。

 

        一句话来讲,调用处理类就是必须以接口实现类为构造参数,对接口的每一个方法都要invoke一下的类。

 

 

     三、如何创建动态代理对象?

 

 

    使用静态工厂的方法,Proxy.newProxyInstance()。

    它的参数:

    1 一个类加载器,一般使用一个已经被加载的对象a上使用 a.class.getClassLoader()获取。

    2 一个希望实现的接口列表。注意,是一个Class类型的数组。

    3 以及一个调用处理器的对象,必须用一个实际上实现了接口的引用对象对它进行初始化。

 

   创建完毕后,记得将它转型为想要实现的某个接口类型,才能给引用赋值。

 

 

    四、动态代理对象如何工作?

 

    当这个代理对象x被赋予某种接口a的引用,然后调用a.b()方法时,虚拟机会执行以下操作:

 

   1 将请求转发到这个动态代理对象的调用处理器类。这个调用处理器类的构造器获得x的引用,将它赋予自己的局部动态代理对象X。b

   2 执行invoke方法,第一个参数传入局部动态代理对象X,第二个参数传入b(),第三个参数传入接口调用时赋予的参数(如果有的话)。

   3 执行invoke方法体,退出。

 

   每次调用x的任何一个方法,invoke方法都会被调用,每次调用第一个参数都是一样的。

 

 

 

 

刚写的一段示例代码:

 

 

 

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

/*
 * 这个类很像AOP的一种用法,在方法执行以前加入某些操作,只有中间层才能做到。*/

interface A
{
	void b();
	void c(String d);
}

class E implements A
{
	public void b()
	{
		System.out.println("This is b.");
	}
	
	public void c(String d)
	{
		System.out.println("This is c's d" + d);

	}

}

class myInvocationHandler implements InvocationHandler
{
	private Object obj;
	public myInvocationHandler(Object obj)
	{
		this.obj = obj;
	}
	
	public Object invoke(Object proxy, Method method,Object[] args) throws Throwable
	{
		System.out.println("This is the object of " + proxy.getClass().getName());
		System.out.println("The method name is  " + method.getName());
		if(args != null)//如果没有这个句子,会出现一个空指针异常。
				for(Object arg : args)
						System.out.println("The argument is  " + arg);

		return method.invoke(obj, args);//极度要注意,这里的obj与proxy不同,proxy的传值我们没有办法控制,我们只能控制object的。
	}
}
public class MyProxy {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		E e = new E();
		A a = (A) Proxy.newProxyInstance(e.getClass().getClassLoader(),//这个classloader的获取做法很奇怪。但是却不能用null。 如果不是强制转换为A类型的话,就可以了。
				new Class[] {A.class}, 
				new myInvocationHandler(e));//这就把e传进调用处理器里面去了。
		Object b = Proxy.newProxyInstance(null,new Class[] {Comparable.class }, new myInvocationHandler(e));//如果要实现的接口不是自定义的,就可以使用null作为类加载器了。如果使用a.class,则必须使用a.getClass.getClassLoader()方法。
		a.b();
		a.c("liang");
		a.c("123");

	}

}
 

分享到:
评论

相关推荐

    Java高级程序设计实战教程第三章-Java反射机制.pptx

    对于任意一个对象,都能够调用它的任意一个方法,常见的应用如下 逆向代码 ,例如反编译 与注解相结合的框架 例如Retrofit 单纯的反射机制应用框架 例如EventBus 2.x 动态生成类框架 例如Gson Java高级程序设计实战...

    Java 基础核心总结 +经典算法大全.rar

    《Java 基础核心总结》 Java 概述 什么是 Java2 Java 的特点Java ...JDK Proxy 和 CGLIB 的对比动态代理的实际应用 Spring AOP 变量 变量汇总实例变量 实例变量的特点全局变量 静态变量 静态变量的特点类变量 局部变量

    JavaScript王者归来part.1 总数2

     6.5.1 动态创建函数--一个利用Function实现Lambda算子的例子   6.5.2 模式--函数工厂及其实例   6.6 总结   第7章 对象  7.1 什么是对象   7.2 对象的属性和方法   7.2.1 对象的内置属性   7.2.2 为...

    asp.net知识库

    ADO.NET 2.0 大批量数据操作和多个动态的结果集 ADO.NET 2.0 异步处理 在ASP.NET中使用WINDOWS验证方式连接SQL SERVER数据库 改进ADO.Net数据库访问方式 ASP.NET 2.0 绑定高级技巧 简单实用的DataSet更新数据库的类+...

    Spring3.x企业应用开发实战(完整版) part1

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    Spring.3.x企业应用开发实战(完整版).part2

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    免费超全面的Java基础类型,容器,并发,IO流,面向对象,Web编程等代码总结

    Proxy动态代理机制详解 从整体上观察对象 网络开发 Servlet基础,生命周期执行过程 Http请求详解,握手挥手流程简介 会话跟踪技术,Session和Cookie详解 过滤器、监听器、拦截器,应用详解 Servlet 集成 C3P0

    庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术

    1.5 运行一个简单的控件 7 1.5.1 开发一个简单控件 7 1.5.2 部署和运行 11 1.6 控件生命周期 12 1.6.1 概述 12 1.6.2 用代码跟踪控件生命周期过程 14 1.7 本章总结 17 第2章 服务器控件开发中的调试技术 18 ...

    WHC 公用类库

    几乎在各个方面,能搜索到有用,发现有用的东西,都逐步积累起来,需要的时候,找到对应的类库,一个可以学习优化现有类库,二个可以发现是否有更好的实现及片段,在积累中学习总结巩固,并在项目中快速应用,也就是...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part1

    1.5 运行一个简单的控件 7 1.5.1 开发一个简单控件 7 1.5.2 部署和运行 11 1.6 控件生命周期 12 1.6.1 概述 12 1.6.2 用代码跟踪控件生命周期过程 14 1.7 本章总结 17 第2章 服务器控件开发中的调试技术 18 ...

    庖丁解牛纵向切入ASP.NET 3.5控件和组件开发技术.pdf

    如果扎实地掌握了asp.net控件的运行机制,开发一个页面级的asp.net应用程序会变得非常简单。本书宗旨就是让开发人员真正理解asp.net技术,帮助开发人员提高asp.net开发的技术水平。学完本书后您不仅能够掌握控件开发...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part2

    1.5 运行一个简单的控件 7 1.5.1 开发一个简单控件 7 1.5.2 部署和运行 11 1.6 控件生命周期 12 1.6.1 概述 12 1.6.2 用代码跟踪控件生命周期过程 14 1.7 本章总结 17 第2章 服务器控件开发中的调试技术 18 ...

    windowsnt 技术内幕

    网络共享资源简介 LAN环境中的命名规则简介 设置共享文件夹权限 当你访问一个资源时,用户和组文件夹权限的应用 使用直观性(Intuitive)好的共享名 理解如何使用缺省的Everyone组权限 使用系统管理共享(Access ...

    python入门到高级全栈工程师培训 第3期 附课件代码

    06 django的一个简单应用 07 django静态文件之static 08 django的url控制系统 09 django的urlConf补充 第50章 01 django之视图函数的介绍 02 django视图之redirec 03 django模板之变量 04 django模板之过滤器 05 ...

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

    15.1.6 动态代理 512 15.2 了解类加载器 515 15.2.1 类加载器层级架构 515 15.2.2 建立classloader实例 518 15.3 重点复习 520 15.4 课后练习 521 chapter16 自定义泛型、枚举与标注 523 16.1 自定义...

    Java学习笔记-个人整理的

    {1.3.1}总结}{23}{subsection.1.3.1} {1.4}数据类型}{23}{section.1.4} {1.4.1}整数与浮点数}{23}{subsection.1.4.1} {1.4.1.1}浮点数原理}{24}{subsubsection.1.4.1.1} {1.4.2}格式化输出浮点数}{24}{...

    Linux多线程服务端编程:使用muduo C++网络库

    1.1.3一个线程安全的Counter 示例.. . . . . . . . . . . . . . . . . . . 4 1.2对象的创建很简单. . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 5 1.3销毁太难. . . . . . . . . . . . . . . . . ....

Global site tag (gtag.js) - Google Analytics