----------------java培训,android培训,期待与你交流-------------------------
一,默认的类加载器
Class.getClassLoader()
返回,该加载器与其元素类型的类加载器是相同的;如果该元素类型是基本类型,则该数组类没有类加载器。
defineClass
来实现的;而启动类的加载过程是通过调用 loadClass
来实现的。前者称为一个类的定义加载器(defining loader),后者称为初始加载器(initiating loader)。在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。两种类加载器的关联之处在于:一个类的定义加载器是它引用的其它类的初始加载器。方法 loadClass()
抛出的是 java.lang.ClassNotFoundException
异常;方法 defineClass()
抛出的是java.lang.NoClassDefFoundError
异常。
类加载器在成功加载某个类之后,会把得到的 java.lang.Class
类的实例缓存起来。下次再请求加载该类的时候,类加载器会直接使用缓存的类的实例,而不会尝试再次加载。也就是说,对于一个类加载器实例来说,相同全名的类只加载一次,即 loadClass
方法不会被重复调用。
类的加载过程从loadClass发起(初始加载器)而真正完成类的加载是通过调用defindClass(类定义加载器),在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。
自定义类加载器时要继承一个系统类加载器,是为了继承类加载器的一些机制。类加载器开始加载文件是从调用classLoader方法开始,loadClass方法内部会自动的去调用findClass,当找到Class文件时会调用defineClass方法,此时完成类的加载过程。
这里我们只需要复写finddClass方法就可以完成自定义类加载器。总的来说复写findClass就是需要将class文件转换为字节数组传给defineClass,defineClass将字节数组转换为Class实例。
二、代理
1,代理概述
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
2,动态代理
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。生成的动态类必须实现一个或多个接口,所以,生成的动态类只能用作具有相同接口的目标类的代理。如果没有则不能生成动态代理类。lCGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
java提供了两个类用于创建动态代理:
InvocationHandler接口
Proxy类,用于动态创建委托类的的代理类。newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)。从这个方法中可以看出,每次调用的时候都有复写接口InvocationHandler中的方法。