2022年JAVA的反射机制与动态代理 .pdf

上传人:Che****ry 文档编号:27256813 上传时间:2022-07-23 格式:PDF 页数:23 大小:333.32KB
返回 下载 相关 举报
2022年JAVA的反射机制与动态代理 .pdf_第1页
第1页 / 共23页
2022年JAVA的反射机制与动态代理 .pdf_第2页
第2页 / 共23页
点击查看更多>>
资源描述

《2022年JAVA的反射机制与动态代理 .pdf》由会员分享,可在线阅读,更多相关《2022年JAVA的反射机制与动态代理 .pdf(23页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、JAVA 的反射机制与动态代理李海峰( QQ:61673110)-A运行时类型信息(RunTime Type Information , RTTI)使得你在程序运行时发现和使用类型信息。 RTTI 主要用来运行时获取向上转型之后的对象到底是什么具体的类型。1.Class对象:JAVA 使用 Class 对象来执行RTTI 。每个类都有一个Class 对象,它用来创建这个类的所有对象,反过来说,每个类的所有对象都会关联同一个Class 对象(对于数组来说,维数、类型一致的数组的Class对象才是相同的),每个对象的创建都依赖于Class 对象的是否创建,Class 对象的创建发生在类加载(jav

2、a.lang.ClassLoader)的时候。java.lang.Class 类实现了 Serializable、GenericDeclaration、Type、AnnotatedElement 四个接口,分别实现了可序列化、泛型定义、类型、元数据(注解)的功能。你可以把Class 对象理解 为一个类在 内存中 的接口 代理(它 代理了这个类的类型信息、方法签名 、属性 ),JVM 加载一个类的时候首先 创建 Class对象, 然后创建这个类的每个实例的时候都使用这个Class对象。Class 只有一个 私有的 无参构造方法 ,也就 是说 Class 的对象创建 只有 JVM 可以 完成。如何

3、验证 同一个类的 多个对象的Class对象是一个 呢?Cf1 cf1 = new Cf1(); Class clazz = Cf1.class ; System. out .println(cf1.getClass() = clazz);我们知道 =用来 比较引 用是否相 等(也就 是同一个 引用),上 面的输出语句结果 是 true。那么 Class对象是否相 等是 JAVA 对象 中唯 一可以使用 =判断 的。如何获取Class 对象:1.所有的 引用数据类型 (类 -类型) 的类 名、基本 数据类型都可以通过.class 方式获取 其 Class对象( 对于基本数据类型的封装类还可以通过

4、.TYPE的方式获取其Class 对象,但要注意 .TYPE实际上获取的封装类对应的基本类型的Class 对象的引用,那么你可以判断出int.class=Integer.TYPE返回 true ,int.class=Integer.class返回 false! ),通过这 种方式不会 初始 化静态域 ,使用 .class、.TYPE 的方式 获取 Class 对象 叫做类的 字面常量;2.Class 的 forName(String name)传入 一个类的 完整 类路径也 可以获得Class 对象, 但由于使用的是 字符串 ,必须强制 转换才可以获取泛型的Class的 Class 对象, 并

5、且你必须获取这个方法 可能 抛出 的 ClassNotFoundException 异常 。2.对于 引 用数据类的 引用( 必须初始 化),可以 通过 Object 类继承 的 getClass()方法 获取这个引 用的 Class 对象, 由于 引用已经被初始 化,所以这 种方式也不 会初始 化静态域 ,因为静态域已经被初始化过。 另外 ,前面 两种方式如果 说是创建 Class 对象, 那么这种方式 应该 是取得 Class 对象, 因为 类的实 例已经被 创建, 那么 Class 对象也一定早就被 创建。Class 的常用方法:lforName(String name):这是一个 静态

6、方法 ,传入 的参数是一个类的 完整 类路径 的字符串 ,返回 这个类的Class 对象, 前面 说过 Class对象的创建发生在类的加载时,所以这个 方法 会 导致静态成 员被调用;lforName(String name,boolean initialize,ClassLoader loader):这是上 面的方名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 23 页 - - - - - - - - - 法的重载方法 ,initialize 指定在创建 Class对象

7、时是否 初始 化这个类( 即是否执行 静态成员,由于在一 次JVM 的执行 中,静态成 员的初始 化只 类加载的时候执行一次,所以 如果之前这个类 已经被 加载, 那么即使initialize 为true也不 会再次 执行 静态成 员的加载),loader指 定使用 哪个类加载 器的实现类(Thread. currentThread().getContextClassLoader()可以获取 当前线程使用的类加载 器)。 forName(*) 方法不 可以获取 基本 数据类型的 Class对象。如果 要测试 initialize 是否 起作 用, 请不要在 main()方法 测试自身 类, 因

8、为 main()是静态方法 ,执行这个 方法 会导 致静态域被初始化,所以你的 initialize 无论是 true还 是false,效果都是一 样的。lasSubClass(Class superClass):这个 方法 是将父 类的 class对象 作为参 数传入 , 并将其强制 转换成 当前的 Class 对象( 子类的 Class 对象)。例:Class clazz = List.class ; Class subClazz = ArrayList.class .asSubclass(clazz); System. out .println(subClazz.getCanonical

9、Name(); 注意红色 的部分不 能写成 Class形 式,因为 asSubclass()只知道 是要转 换成 子类的 Class 对象, 但不知道 是哪个 子类。lcast(Object o) : 这个 方法 是将传入 的对象 强制 转换成 Class 对象所 代表的类型的对象;lgetClassLoader():返回 创建 当前 Class 对象的类加载 器,默认 的, 应用程序获得的是sun.misc.Launcher$AppClassLoader,Applet程序获得的是sun.applet.AppletClassLoader;lgetCanonicalName(): 返回 JAVA

10、 语言中所定义的底 层类的 规范 化名称,如果 没 有规范 化名称就 返回 null,对于 普通的引用数据类型,这个方法 和 getName()方法 都返回完整 的类 路径 ,对于数组(以字符串 数组 为例 ) ,getName()返回Ljava.lang.String;,这个方法返回 java.lang.String;lgetSimpleName():返回 底层规范 化名称的简写 ,也就 是去掉包 名;lgetConstructors():返回 Class 对象的 公有构造 器的 java.lang.reflect.Contructor对象数组, 如果 找 不到匹配 的构造方法 ,返回 No

11、SuchMethodExcetion 异常;lgetConstructor(Class parameterTypes):按照指 定的可 变参数列 表,返回符合参数条件 的公有构造方法 的 Constructor,这里 不可能是数组, 因为构造方法不可能重复 ,如果 找 不到匹配 的构造方法 ,返回 NoSuchMethodExcetion 异常;lgetDeclaredConstructors(): 返回 Class 对象的所有 构造 器的 Constructor 对象, 如果找不到匹配 的构造方法 ,返回 NoSuchMethodExcetion 异常;lgetDeclaredConstru

12、ctor(Class parameterTypes):按照指 定的可 变参 数列表,返回 符合 参数条件 的所有 构造方法 的 Constructor,这里不可能是数组, 因为构造方法不 可能 重复 ,如果 找不到匹配 的构造方法 ,返回 NoSuchMethodExcetion 异常;lgetFields():获取 Class对象的所有 公有成 员属性 的 java.lang.reflect.Field 数组 ;lgetField(String name):按照 字段名称 获取 公有字段的 Field 对象,注 意 name是区分大小写 的;lgetDeclaredFields():获取 C

13、lass对象的所有 成员 属性 的 Field 数组 ;lgetDeclaredField(String name):按照 字段名 称获取所有 字段 的 Field 对象,注 意name是 区分大小写 的;lgetMethods(): 获取 Class 对象的 公 有方法 (以 及从父 类继承 的方法 ,但不 包含 构造名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 23 页 - - - - - - - - - 方法 )的 java.lang.reflect.Method

14、 数组 ;lgetMethod(String name,Class parameterTypes):按照 name指定的 方法名称,parameterTypes指定的可 变数组获取 公有方法 (以 及从父 类继承 的方法 ,但不 包含构造方法 )的 Method 对象,注 意 name是 区分大小写 的 ;lgetDeclaredMethods():获取 Class 对象的所有 方法(不包含父 类 继承 的方法 ,构造方法 )的 Method 数组 ;lgetDeclaredMethod(String name,Class parameterTypes):按照name指定的 方法名 称,par

15、ameterTypes指定的可 变数组获取所有 方法 (不 包含父 类继承 的 方法,构造方法 )的 Method 对象,注 意 name是区分大小写 的;lgetGenericInterface():以 Type 数组的 形式返回 Class 对象的类 直接实现的 包含 泛型参数的接口, 返回顺 序是 implements 后的接口 顺序;lgetInterface():以 Class数组的 形式返回 Class对象的类 直接实现的接口,返回顺 序是 implements 后的接口 顺序 ;lgetModifiers():以 java.lang.reflect.Modifier的 常量 值的

16、形式返回 Class 对象的类的 修饰的整型值的和 ;lgetGenericSuperclass(): 以 Type 数组的 形式 返回 Class 对象的类 直接实现的 包含 泛型参数的 超类 , 返回顺 序是 extends后的接口 顺序;lgetSuperclass(): 以 Class 数组的 形式返回 Class 对象的类 直接实现的 超类, 返回顺 序是 extends后的接口 顺 序;lgetName():以 String 形式返回 Class 对象所 表示 的实体的 完整 类 名,基本 数据类型返回自身 ,数组类型(以String 数组 为例 )返回 Ljava.lang.St

17、ring;,这个 方法 没 有getCanonicalName()返回 的完整 ,但不 是所有的类型都有底层的规范 化名称;lgetPackage():以 java.lang.reflect.Package 形 式返回 Class 对象的类所在的包,基本 数据类型、数组抛出异常;lgetResource(String url): 这个 方法 使用 当 前 Class对象的 ClassLoader实体加载url指定的 资源 , 返回 .URL 对象。 如果 url 以 开头 ,那么就从当 前的 classPath开始定位资源 ,否 则就从当 前 Class 对象的类所在的包开 始 定位资源 ,H

18、ibernate 要 求*.hbm.xml 必须 和 PO 类在一个 包下 , 就是利用了 没有 开头 的 url 传入 这个 方法 实现的;lgetResourceAsStream(String url):这个 方法 和上 面的方法 一样 ,只不 过返回 的是java.io.InputStream 的对象 ;lisAssignableFrom(Class class) :判断 当前 Class对象的类是否是参 数 class的类的 超类或者 接口 ;lisInstance(Object o): 判断参 数 o 是否是 Class对象的类的实 例, 相当于 o instanceOf Class

19、。isInstance()、instanceOf 关键字检查 的某个实 例是否是这个类型,具有继承 关系的 检查 能力,即 使 是 其 子 类 的 对 象 , 也 可 以 返 回true 。 但 是Class 对 象 是 严 格 的 类 型 , 所 以super.class=sub.class是一定 返回 false 的。lnewInstance():这个 方法 将会使得Class 对象 调 用类 中的公有无参构造方法实例 化对象, ,返回 一个 Object 对象,大多数框架 都会使用到这个方法 ,例如 EJB 容 器、Spring容器都会要 求 受管 组件提供 一个 默认 构造方法 。注意

20、: 以上的 方法并不 是对每 种类型都可用, 对于 返回 数组的 方法 ,如果不 可用 则返回 长度为 0 的数组,对于返回 其 他类型的 方法 , 如果不 可用 则返回null。例如 : getConstructors()名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 23 页 - - - - - - - - - 方法 对于 基本 数据类型、数组就不 可用, 那么返回 一个 长度 为 0 的 Constructor 数组。另外 , 上 面的方法 获取类 中的元 素大都是

21、 只能获取 public 的元 素,可以获取 全部元素的大 都是含 有 Declared 字符 。某些 方法不 具有 递归特 性, 例如只 能查找 本类的元 素, 不能查找 内部 类或者 其父类 中的元 素,如果 你非要这么 做 ,需要自行递归操 作,例如 :调 用 getSuperClass()直到 其返回 null 为止 。_ 2.JAVA的反射机制:前面 说过 RTTI 获取 某个对象的 确切 类型,要 求在这个对象在编译 时必须已知 ,也就 是必须已经 在你的 代码中存 在完整 的声明 (T t) ,但是如果 是运行时才会知晓的对象( 例如 网络 中传递 过来的 字节) ,RTTI 就

22、没办法工 作了。java.lang.Class 与 java.lang.reflect.* 包中的类 提供 了一 种有别于 RTTI(编译 器在编译 器时 打开和 检查 *.class 文件 )的反 射机 制(运行时 打开和检查 *.class 文件) 。JAVA 的反 射 功能相 当强大 ,例如前面 说过的类的 复用方式 -组合,如果 是动态组合的新 类就叫 聚合,反 射就 可以 完成 聚合功能。(1.)Field:这个类用于获取类中的字段信息以及访问这些字段的能力。lgetObject(Object o):返回 参数 o 的对象上的Field 表示 的字段的 值;lsetObject(Ob

23、ject o,Object value):将参 数 o 的对象上的Field 表示 的字段的值 设置为 value;lgetBoolean(Object o): 获取 参 数 o 的对象的Field 表示 的布尔 类型的 字段的值;lsetBoolean(Object o,boolean value):将参数 o 的对象上的Field 表示 的布尔 类型的字段的值设置 为 value; 对于 基本 数据类型,都拥有自己的 getXXX() 、 setXXX() 方法 。lgetGenericType():返回 Field 表示 的字 段声明 的泛型类型的Type 实例;lgetModifier

24、s():以整型数 值和的 形式返回 Field 表示 的字段的修饰 符;lgetType(): 返回 Field 表示 的字段的类型的Class 对象 ;lisEnumConstants():如果 Field 表示 的字 段是枚举 类型, 返回 true;ltoGenericString():返回 描述此 字段的字符串 (包含 泛型信息),能 够包含 泛型信息是与 toString() 方法 的唯一区别。例:publicclass Reflect1 privateint i; protected String s; public List list = new ArrayList(); pub

25、lic Reflect1() System. out .println(default); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 23 页 - - - - - - - - - protected Reflect1(String name) System. out .println(name); publicvoid f() System. out .println(invoke f); String mf(int j, Object. args) System.

26、 out .println(invoke mf); return String. valueOf (j + args.length ); publicclass Rf publicstaticvoid main(String args) throws Exception Class clazz = Reflect1.class ; Reflect1 rf1 = clazz.newInstance(); / 含有 Declared 字符串的是获取所有的元素,否则就只能获取公有元素Field f = clazz.getDeclaredFields(); for (Field field : f)

27、/ 设置这里本不具有访问权限的元素为可访问field.setAccessible(true ); / 使用基本数据类型专有的APIif (field.getType().getCanonicalName().equals(int ) | field.getType().getCanonicalName().equals( java.lang.Integer) field.setInt(rf1, 9); System. out .println(Field is + field.getName() + t+ field.toGenericString() + t + field.get(rf1)

28、; 控制台输出如下语句:default Field is i private int net.ilkj.reflect.Reflect1.i 9 Field is s protected java.lang.String net.ilkj.reflect.Reflect1.s null Field is list public java.util.List net.ilkj.reflect.Reflect1.list _ (2.)Method:这个类用于获取类中的方法的信息以及访问这些方法的能力。lgetDefaultValue():返回 此 方法 表示 的注 视成员的默认值 ;名师资料总结

29、- - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 23 页 - - - - - - - - - lgetParameterAnnotations():返回 一个 Annotation 的二维数组, 表示方法 的参数列表的参数的注解 ;lgetExceptionTypes():返回 这个 方法抛出 的(底 层)异常 的 Class数组 ;lgetGenericExceptionTypes():返回 这个 方法抛出 的异常 的 Type 数组, 包含 泛型信息;lgetParameterTy

30、pes(): 返回 这个 方法 的参数列 表的 Class 对象数组 ;lgetGenericParameterTypes(): 返回 这个 方法 的参数列 表的包含 泛型信息的Type对象数组, 例如 一个 List 的参 数前面 的方法会获得java.util.List,而这个 方法会获得 java.util.List;lgetReturnType():获取 方法 返回值 的类型的Class 对象;lgetGenericReturnType():获取 方法 返回值 的类型的 Type 对象, 含有泛型信息 ;lisBridge(): 如果 此方法 是 bridge 方法 ,返回 true;

31、lisVarArgs():如果 此方法 的参数列 表中含有可变参数,返回 true;linvoke(Object o,Object args) : 使用类的对象和可变参数列表调 用这个 方法,这个方法 返回 Object 对象, 也就 是类 中的这个 方法 的返回值 ;lgetTypeParameters():以 java.lang.reflect.TypeV ariable 数组 返回 Method 对象的泛型方法 的类型 参 数,数组的 顺序是泛型定义的类型的顺序;ltoGenericString():返回 描述此 方法 的字符串 (包含泛型信息),能 够包含 泛型信息是此方法 与 toS

32、tring() 方法 的唯 一区别。例:publicclass Reflect1 privateint i; protected String s; public List list = new ArrayList(); public Reflect1() System. out .println(default); protected Reflect1(String name) System. out .println(name); publicvoid f() throws NumberFormatException, ArrayIndexOutOfBoundsException Syst

33、em. out .println(invoke f); String mf(List list, Object. args) throws X System. out .println(invoke mf); return String. valueOf (list.size() + args.length); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 23 页 - - - - - - - - - publicclass Rf publicstaticvoid ma

34、in(String args) throws Exception Class clazz = Reflect1.class ; Reflect1 rf1 = clazz.newInstance(); Method m = clazz.getDeclaredMethods(); for (Method method : m) Class cs = method.getParameterTypes(); System. out .println(Method is + method.getName(); / 获取泛型的 异常Type t = method.getGenericExceptionTy

35、pes(); for (Type type : t) System. out .println(GenericException is + type.toString(); / 获取普通的 异常Class cc = method.getExceptionTypes(); for (Class c : cc) System. out .println(Exception is + c.getCanonicalName(); if (cs. length = 2) if (cs0.getCanonicalName().equals(java.util.List) & cs1.getCanonica

36、lName() .equals( java.lang.Object) Object o = method.invoke(rf1, new ArrayList(), new Object 2 ); System. out .println(The Return Value is + o); 控制 台输出如 下语句 :default Method is mf GenericException is X Exception is java.lang.Exceptioninvoke mf The Return Value is 1 Method is f GenericException is cla

37、ss java.lang.NumberFormatExceptionGenericException is class java.lang.ArrayIndexOutOfBoundsExceptionException is java.lang.NumberFormatExceptionException is java.lang.ArrayIndexOutOfBoundsException名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 23 页 - - - - - -

38、- - - 注意红色 的代码,你 就能区分出含有 Generic 字符串 的方法 和不含有这个 字符串 的方法 的 区别了。_ (3.)Constructor:这个类用于获取类中的构造方法的信息以及访问这些构造方法的能力。构造方法由 于比较 特殊 ,所以 单独 作为一个类, 但 是它的 方法 和 Method 没有任何区别。_ (4.)Member接口:Class、Field、Method、Constructor都实现了Member接口,表明他们是类的成员。lgetDeclaringClass(): 返回 此 成员所属的类的 Class 对象 ;lgetModifiers():以整型值 的和的

39、 形式返回 这个 成员的修饰 符;lgetName():返回 此 成员的名称的字符串;lisSynthetic():如果 此成员是编译 器 引入 的, 返回 true。_ (5.)AccessibleObject类:Class、Field、Method(注意没有Constructor,可见构造方法的访问级别绝对不可以改变!)都扩展了AccessibleObject类,这个类提供了取消JAVA访问权限的限制。lgetAnnotation(Class annotationClass):返回 这个 成员上 指定注解类型的注解;lgetAnnotations(): 返回 这个 成员 上的所有注解的An

40、notation 数组 ;lgetDeclaredAnnotations():返回直 接应用在 此元素上的注解的Annotation 数组 ;lisAccessible():如果 该成员在 当前位置可以 被 访问 ,返回 true;lisAnnotationPresent(Class annotationClass):返回指定的 annotationClass 是否 存在于 当前的成员;lsetAccessible(boolean bool) :设置此 元素是否可以在 当前位置访问 ,这个 方法 在外面 访问 类中 的私有成员时, 非常有用 处;lsetAccessible(Accessibl

41、eObject array,boolean flag):这是一个 静态方法 ,你可以 将一组 成 员包 装成 AccessibleObject 数组,一 并设置他 们的访问 性 。_ (6.)Modifier:这个类存放了所有修饰符的常量值,以及通过这些常量值判断是哪种修饰符。你可以 将 getModifiers() 方法 返回 的 int 类型 传入 这个类的isXXX() 静态方法 ,判断 是哪种 修饰符 。_ (7.)Array:这个类提供了动态创建和访问数组的能力。这个类 中的方法 全 部是静态方法 ,它 允许 在 get()、set()方法 时进行扩展 转型, 如果 进行收缩转型,

42、将会抛出 非 法的参数异常 。这个类的 方法 都是 静态方法 。lget(Object o,int index):获取 指定数组 中的索引位 置 index 上的元 素;lset(Object o,int index,Object value):设置 指定数组 中的索 引位置 index 上的元 素名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 23 页 - - - - - - - - - 为 value;getXXX() 、setXXX() 可以 直接设置 基本 数据类

43、型 ;lnewInstance(Class componentType,int length): 创 建 一 个 指 定 类 型 为componentType 的长度 为 length 的一维数组 ;lnewInstance(Class componentType,intargs): 创 建 一 个 指 定 类 型 为componentType 的 args指定的维数的 多维数组 ;例:publicclass Rf publicstaticvoid main(String args) throws Exception / 创建一个二维 数组,第一维 有三个元素, 第二维 有两个元素Person

44、 i = (Person) Array.newInstance(Person. class , 3, 2); Array. set (i0, 0, new Child(); System. out .println(Array.get (i0, 0); class Person class Child extends Person _ 3.动态代理:要看清楚 什么是 动 态代 理的, 首先我们 来看一下静态代 理的 做法 。无论是那种代 理方式 ,都存在 代理对象和 目标 对象 两个模型, 所谓目标 对象 就是我们 要生 成的代理对象所 代理的那个对象。(1.) 包装的 模式进行静 态代理:接

45、口 :Animal publicinterface Animal void eat(String food); String type(); 实现 类: Monkey publicclass Monkey implements Animal Overridepublic String type() 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 23 页 - - - - - - - - - String type = 哺乳动物 ; System.out .println(

46、type); return type; Overridepublicvoid eat(String food) System.out .println(The food is + food + !); 包装类: AnimalWrapper publicclass AnimalWrapper implements Animal private Animal animal; / 使用 构造方法 包装Animal的接口,这 样所有的Animal实现类都可以 被这个Wrapper包装。public AnimalWrapper(Animal animal) this. animal = animal;

47、Overridepublicvoid eat(String food) System.out .println(+Wrapped Before!+); animal.eat(food); System.out .println(+Wrapped After!+); Overridepublic String type() System.out .println(-Wrapped Before!-); String type = animal.type(); System.out .println(-Wrapped After!-); return type; 运行程序 :AnimalWrapp

48、er aw = new AnimalWrapper(new Monkey(); aw.eat( 香蕉 ); aw.type();名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 23 页 - - - - - - - - - 控制台输出如下语句:+Wrapped Before!+ The food is 香蕉 ! +Wrapped After!+ -Wrapped Before!- 哺乳动物-Wrapped After!- 这里 我们完成 了对 Animal 所有 子类的

49、代理,在 代理方法中 ,你可以加 入一些自己的额外的处理 逻辑 ,就像上 面的+、-输出语句 一样。那么 Spring 的前置、后 置、环绕方法通知 ,通过这 种方式 可以有 限的模拟 出来,以Spring 的声明 式事务为例 ,无非就是在调用包装的目标 方法 之前处开 启事务 ,在之后 提交事务 ,这样原有的 业务逻辑 没有受到任何事务 管理代码的 侵入。这种方式 的静态代 理, 缺点 就是当 Animal 接口 中增加了 新的方法 ,那么包装类中也必须 增加这 些新 的方法 。(2.) 继承 的模式进行静 态代理:继承 类: MyMonkey publicclass MyMonkey ex

50、tends Monkey Overridepublicvoid eat(String food) System.out .println(+Wrapped Before!+); super .eat(food); System.out .println(+Wrapped After!+); Overridepublic String type() System.out .println(-Wrapped Before!-); String type = super .type(); System.out .println(-Wrapped After!-); return type; 这个 例

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com