反射(十二)

12.1 Class类

1.Class类

1)对象照镜子后可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个类的有关信息。

2)Class对象只能由系统建立对象

3)一个类在JVM中只会有一个Class实例

4)每个类的实例都会记得自己是由哪个Class实例所生成

2.获取Class对象的方式

3.Class类的常用方法

方法名 功能说明
static Class forName(String name) 返回指定类名name的Class对象
Object newInstance() 调用缺省构造函数,返回该Class对象的一个实例
Object newInstance(Object []args) 调用当前格式构造函数,返回该Class对象的一个实例
getName() 返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
Class getSuperClass() 返回当前Class对象的父类的Class对象
Class [] getInterfaces() 获取当前Class对象的接口
ClassLoader getClassLoader() 返回该类的类加载器
Class getSuperclass() 返回表示此Class所表示的实体的超类的Class

12.2 Java的类加载机制

12.3 使用ClassLoader进行类加载

类装载器是用来把类(class)装载进JVM的。JVM规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。JVM在运行时会产生3个类加载器组成的初始化加载器层次结构,如下图所示:

演示类加载机制的层次关系:

public class ClassLoaderDemo {                                                                                                                                                                    public static void main(String[] args) {                                                                                                                                                          ClassLoader classloader;                                                                                                                                                                   //获取系统缺省的ClassLoader                                                                                                                                                           classloader = ClassLoader.getSystemClassLoader();                                                                                                                       System.out.println(classloader);                                                                                                                                                        while (classloader != null) {                                                                                                                                                                                 //取得父的ClassLoader                                                                                                                                                                       classloader = classloader.getParent();                                                                                                                                                System.out.println(classloader);                                                                                                                                       }

执行结果如下:                                                                                                                                                                                //表示系统类装载器实例化自类sun.misc.Launcher$AppClassLoader                                                                                  sun.misc.Launcher$AppClassLoader@19821f                                                                                                                                   //表示系统类装载器的parent实例化自类  sun.misc.Launcher$ExtClassLoader                                             sun.misc.Launcher$ExtClassLoader@addbf1                                                                                                                                //表示系统类装载器parent的parent为bootstrap,无法直接获取                                                                                                      null                                                                                                                                                                                                    //表示类Object是由bootstrap装载的                                                                                                                                java.lang.Object's loader is  null                                                                                                                                                       //表示用户类是由系统类装载器装载的                                                                                                                                ClassLoaderDemo's loader is  sun.misc.Launcher$AppClassLoader@19821f

12.4 反射的机制

1.反射概念

Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection  API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

2.Java反射机制主要提供了以下功能:

---在运行时任意构造一个类的对象

---在运行时获取任意一个类所具有的成员变量和方法

---在运行时调用任意一个对象的方法(属性)

---生成动态代理

12.5 Constructor、Method、Field 类的用法

1.在运行时构造一个类的对象

1)调用Class对象的newInstance()方法

2)调用 Constructor 对象的 newInstance(Object... initargs)

2.Constructor对象

1)代表构造器对象

2)获取Constructor

3)相关方法

---newInstance(Object... initargs)

---setAccessible(boolean flag)

3.Method(Field) 对象

1)代表方法

2)Class对象获取Method的方法:

---getDeclaredMethod(String name, Class<?>... parameterTypes)

---getDeclaredMethods()

---getMethod(String name, Class<?>... parameterTypes)

---getMethods() 

3)Method对象的方法

---invoke(Object obj, Object... args)

4.Annotation 相关

以Method为例:

---获取Annotation 实例:

---getAnnotation(Class<T> annotationClass)

---getDeclaredAnnotations()

---getParameterAnnotations()

5.泛型相关

1)获取父类泛型类型:Type getGenericSuperclass()

2)泛型类型:ParameterizedType

3)获取实际的泛型类型参数数组:getActualTypeArguments()

12.6 动态代理

1.创建动态代理

1)Proxy 提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。

2)Proxy 提供了两个方法来创建动态代理类和动态代理实例。

2.使用动态代理实现AOP

AOP(Aspect Orient Program, 面向切面编程)

3.非模块化的横切关注点所带来的问题

横切关注点:跨越应用程序多个模块的功能

代码实现片段

4.问题

越来越多的非业务需求(日志和验证)加入后,原有的计算器方法急剧膨胀。

属于系统范围内的需求通常需要跨越多个模块(横切关注点),这些类似的需求包括日志,验证,事务等。

5.非模块化的横切关注点将会导致的问题

1)代码混乱:每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。

2)代码分散:以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块里多次重复相同的日志代码。如果日志需求发生变化,必须修改所有模块。

6.使用动态代理模块化横切关注点

代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

代码实现:

测试代码:

猜你喜欢

转载自blog.csdn.net/shizhudufou/article/details/82378821
今日推荐