java反射与代理模式
流程age:
饭前洗手----》 吃饭 ---》饭后洗碗
- //吃饭
- public interface Dinner {
- //吃饭方法
- public void haveDinner();
- }
- //委托类
- public class MyDinner implements Dinner {
- @Override
- public void haveDinner() {
- System.out.println("吃饭");
- }
- }
代理类实现InvocationHandler 接口
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- //代理类
- public class MyDinnerProxy implements InvocationHandler {
- private Object originalObject;//被代理的原始对象
- //绑定被代理对象,返回一个代理对象
- public Object bind(Object obj){
- this.originalObject = obj;
- //返回:一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
// newProxyInstance参数: 类加载器,全部接口 指派方法调用的调用处理程序- return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
- }
- //吃饭前要执行的方法
- private void preMethod(){
- System.out.println("饭前洗手 ");
- }
- //吃饭后执行的方法
- private void afterMethod(){
- System.out.println("吃饭后");
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- Object result = null;
- preMethod();
- result = method.invoke(this.originalObject, args);
- System.out.println("rsult:"+result);
- afterMethod();
- return null;
- }
- }
- public class MyDinnerProxyDemo {
- public static void main(String[] args) {
- //1
- Dinner dinner = new MyDinner();
- dinner.haveDinner();
- //2
- MyDinnerProxy proxy = new MyDinnerProxy();
- //返回一个代理对象
- dinner = (Dinner) proxy.bind(dinner);
- //执行代理对象的方法
- dinner.haveDinner();
- }
- }
- public class Proxyextends Objectimplements Serializable
Proxy
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
创建某一接口 Foo
的代理:
- InvocationHandler handler = new MyInvocationHandler(...);
- Class proxyClass = Proxy.getProxyClass(
- Foo.class.getClassLoader(), new Class[] { Foo.class });
- Foo f = (Foo) proxyClass.
- getConstructor(new Class[] { InvocationHandler.class }).
- newInstance(new Object[] { handler });
或使用以下更简单的方法:
- Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- new Class[] { Foo.class },
- handler);
动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象,它可以实现接口 InvocationHandler
。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke
方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method
对象以及包含参数的 Object
类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。
代理类具用以下属性:
- 代理类是公共的、最终的,而不是抽象的。
- 未指定代理类的非限定名称。但是,以字符串
"$Proxy"
开头的类名空间应该为代理类保留。 - 代理类扩展
java.lang.reflect.Proxy
。 - 代理类会按同一顺序准确地实现其创建时指定的接口。
- 如果代理类实现了非公共接口,那么它将在与该接口相同的包中定义。否则,代理类的包也是未指定的。注意,包密封将不阻止代理类在运行时在特定包中的成功定义,也不会阻止相同类加载器和带有特定签名的包所定义的类。
- 由于代理类将实现所有在其创建时指定的接口,所以对其
Class
对象调用getInterfaces
将返回一个包含相同接口列表的数组(按其创建时指定的顺序),对其Class
对象调用getMethods
将返回一个包括这些接口中所有方法的Method
对象的数组,并且调用getMethod
将会在代理接口中找到期望的一些方法。 - 如果
Proxy.isProxyClass
方法传递代理类(由Proxy.getProxyClass
返回的类,或由Proxy.newProxyInstance
返回的对象的类),则该方法返回 true,否则返回 false。 - 代理类的
java.security.ProtectionDomain
与由引导类加载器(如java.lang.Object
)加载的系统类相同,原因是代理类的代码由受信任的系统代码生成。此保护域通常被授予java.security.AllPermission
。 - 每个代理类都有一个可以带一个参数(接口
InvocationHandler
的实现)的公共构造方法,用于设置代理实例的调用处理程序。并非必须使用反射 API 才能访问公共构造方法,通过调用Proxy.newInstance
方法(将调用Proxy.getProxyClass
的操作和调用带有调用处理程序的构造方法结合在一起)也可以创建代理实例。
代理实例具有以下属性:
- 提供代理实例
proxy
和一个由其代理类Foo
实现的接口,以下表达式将返回 true:-
proxy instanceof Foo
并且以下的强制转换操作将会成功(而不抛出
ClassCastException
):-
(Foo) proxy
-
- 每个代理实例都有一个关联的调用处理程序,它会被传递到其构造方法中。静态
Proxy.getInvocationHandler
方法将返回与作为其参数传递的代理实例相关的调用处理程序。 - 代理实例上的接口方法调用将按照该方法的文档描述进行编码,并被指派到调用处理程序的
Invoke
方法。 - 在代理实例上的
java.lang.Object
中声明的hashCode
、equals
或toString
方法的调用将按照与编码和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的invoke
方法,如上所述。传递到invoke
的Method
对象的声明类是java.lang.Object
。代理类不重写从java.lang.Object
继承的代理实例的其他公共方法,所以这些方法的调用行为与其对java.lang.Object
实例的操作一样。
在多代理接口中重复的方法
当代理类的两个或多个接口包含一个具有相同名称和参数签名的方法时,代理类的接口顺序变得非常重要。在代理实例上调用重复方法 时,传递到调用处理程序的 Method
对象没有必要成为其声明类可以从接口(通过该接口调用代理方法)的引用类型指派的对象。此限制存在的原因是,生成的代理类中的相应方法实现无法确定它通过哪一个接口调用。因此,在代理实例上调用重复方法时,第一个接口中的方法的 Method
对象包含接口的代理类列表中的方法(直接或通过超级接口继承),该对象会传递到调用处理程序的 invoke
方法,无论该方法调用通过哪一种引用类型发生。
如果代理接口包含某一方法,它的名称和参数签名与 java.lang.Object
的 hashCode
、equals
或 toString
方法相同,那么在代理实例上调用这样的方法时,传递到调用处理程序的 Method
对象将使 java.lang.Object
成为其声明类。换句话说,java.lang.Object
公共的非最终方法理论上在所有代理接口之前,以便确定哪一个 Method
对象传递到调用处理程序。
还要注意,当重复方法被指派到调用处理程序时,invoke
方法只可以抛出经过检查的异常类型,该异常类型可以使用所有 代理接口(可以通过它调用)中方法的 throws
子句指派一种异常类型。如果 invoke
方法抛出一个经过检查的异常,该异常没有指派给任何由一个代理接口(可以通过它调用)中的方法声明的异常类型,那么该代理实例上的调用将抛出一个未经检查的 UndeclaredThrowableException
。此限制表示并非所有的由传递到 invoke
方法的 Method
对象上调用 getExceptionTypes
返回的异常类型都可以由 invoke
方法成功抛出。
java反射与代理模式的更多相关文章
- (转)轻松学,Java 中的代理模式及动态代理
背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- java设计模式6——代理模式
java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...
- 说说Java中的代理模式
今天看到传智播客李勇老师的JDBC系列的第36节——通过代理模式来保持用户关闭连接的习惯.讲的我彻底蒙蔽了,由于第一次接触代理模式,感到理解很难,在博客园找到一篇文章,先记录如下: 引用自java设计 ...
- java反射机制(工厂模式)
http://www.phpddt.com/dhtml/338.html java里面没有typeof,js有. 我终于实现了用反射机制编写的工厂模式.java反射在工厂模式可以体现. 包含产品接口类 ...
- 谈谈Java中的代理模式
首先来看一下代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是代理类与 ...
- 【译】11. Java反射——动态代理
原文地址:http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html 博主最近比较忙,争取每周翻译四篇.等不急的请移步原文网页. ...
- Java设计模式:代理模式(转)
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...
- Java设计模式之代理模式(Proxy)
前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...
随机推荐
- 《深入理解javascript原型和闭包系列》 知识点整理
深入理解javascript原型和闭包系列 对原型和闭包等相关知识的讲解,由浅入深,通俗易懂,每个字都值得细细研究. 一.一切都是对象 1. typeof操作符输出6种类型:string boolea ...
- Javascript编程模式(JavaScript Programming Patterns)Part 2.(高级篇)
模块编程模式的启示(Revealing Module Pattern) 客户端对象(Custom Objects) 懒函数定义(Lazy Function Definition) Christian ...
- eCos中断模型
http://blog.csdn.net/chychc/article/details/8313458 http://www.cnblogs.com/RandyQ/archive/2013/04/14 ...
- USB CDC类
现代嵌入式系统中,异步串行通信接口往往作为标准外设出现在单片机和嵌入式系统中.但是随着个人计算机通用外围设备越来越少地使用串口,串口正在逐渐从个人计算机特别是便携式电脑上消失.于是嵌入式开发人员常常发 ...
- Android 性能优化之使用MAT分析内存泄露问题
我们平常在开发Android应用程序的时候,稍有不慎就有可能产生OOM,虽然JAVA有垃圾回收机,但也不能杜绝内存泄露,内存溢出等问题,随着科技的进步,移动设备的内存也越来越大了,但由于Android ...
- JNI编程(二) —— 让C++和Java相互调用(1)
自己在外面偷偷的算了下,又有将近两个月没更新过blog了.趁着今天有兴致,来更新JNI编程的第二篇文章.在第一篇里,大概介绍了JNI的特点.用途和优劣.并且做一个最简单的JNI的例子,不过说实话那个例 ...
- 【HDOJ】2828 Lamp
DLX简单题目. /* */ #include <iostream> #include <sstream> #include <string> #include & ...
- istringstream、ostringstream、stringstream 类介绍 .
istringstream.ostringstream.stringstream 类介绍 . 转自:http://www.cnblogs.com/gamesky/archive/2013/01/09/ ...
- cocos2dx 实用小技巧
Menu 的 是个 很方便的 按钮 c2dx 默认为 MenuItemLabel 添加的 按下 变大 的 动画 却没有 给 MenuItemSprite 提供这样的效果 如果 自己 不想 封装新的 动 ...
- [转] AC自动机详解
转载自:http://hi.baidu.com/nialv7/item/ce1ce015d44a6ba7feded52d AC自动机详解 AC自动机是用来处理多串匹配问题的,即给你很多串,再给你一篇文 ...