共计 2173 个字符,预计需要花费 6 分钟才能阅读完成。
动静代理
代理对象存在的价值:次要用于拦挡对实在业务对象的拜访。
代理对象有什么办法?
当初要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。
如何编写生成代理对象的类,两个因素:
代理谁
如何生成代理对象
代理谁?
设计一个类变量,以及一个构造函数,记住代理类 代理哪个对象。
如何生成代理对象?
设计一个办法生成代理对象(在办法内编写代码生成代理对象是此处编程的难点)
Java 提供了一个 Proxy 类,调用它的 newInstance 办法能够生成某个对象的代理对象,应用该办法生成代理对象时,须要三个参数:
1. 生成代理对象应用哪个类装载器
2. 生成哪个对象的代理对象,通过接口指定
3. 生成的代理对象的办法里干什么事,由开发人员编写 handler 接口的实现来指定。
初学者必须必须记住的 2 件事件:
Proxy 类负责创立代理对象时,如果指定了 handler(处理器),那么不论用户调用代理对象的什么办法,该办法都是调用处理器的 invoke 办法。
因为 invoke 办法被调用须要三个参数:代理对象、办法、办法的参数,因而不论代理对象哪个办法调用处理器的 invoke 办法,都必须把本人所在的对象、本人(调用 invoke 办法的办法)、办法的参数传递进来。
AOP:面向切面的编程
AOP 的底层实现就是通过动静代理来做到的。
动静代理
在代理模式根底上倒退的,它不在是对繁多的类型进行代理,而是能够对任意的一个实现了接口的类的对象做代理。
动静代理实现
两种形式:
1. 通过 jdk 中提供的 Proxy 类来实现
这种形式要求,被代理类必须实现接口,即只能为接口做代理.
2. 通过 cglib 来实现,它不要求实现接口。
第一种形式的代码实现:
Proxy 类中有一个办法 newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h);
参数:
loader: 要求,传递的是被代理类的类加载器 ClassLoader
类加载器怎么获取:
失去其 Class 对象,在 Class 类中提供一个办法 getClassLoader();
interfaces: 要求: 失去被代理对象所实现的接口的所有 Class 对象。
怎么获取所有实现接口的 Class 对象?
失去其 Class 对象,在 Class 类中提供一个办法 getInterfaces(); 它返回的是 Class[], 就代表所实现接口的所有 Class 对象。
h: 它的类型是 InvocationHandler,这是一个接口。
InvocationHandler 是代理实例的调用处理程序 实现的接口。
InvocationHandler接口中有一个办法invoke;
参数 proxy 就是代理对象
参数 method 就是调用办法
参数 args 就是调用的办法的参数
返回值, 就是实在行为执行后返回的后果,会传递给代理对象调用的办法.
public Object invoke(Object proxy, Method method, Object[] args);
演示类加载器
问题: 类加载器如果获取?
在 Class 类中有一个办法 getClassLoader()它返回的就是一个类加载器.
1. 获取疏导类加载器
ClassLoader cl = String.class.getClassLoader();
System.out.println(cl);
后果是 null.
起因: 疏导类加载器非凡,它基本就不是 java 实现。所有在失去疏导类回载器是后果就是 null.
2. 扩大类加载器
ClassLoader cl = AccessBridge.class.getClassLoader();
System.out.println(cl); //sun.misc.Launcher$ExtClassLoader@9cb0f4
3. 利用类加载器
ClassLoader cl = this.getClass().getClassLoader();
System.out.println(cl); //sun.misc.Launcher$AppClassLoader@164dbd5
全盘负责委托机制
全盘负责:即是当一个 classloader 加载一个 Class 的时候,这个 Class 所依赖的和援用的其它 Class 通常也由这个 classloader 负责载入。
委托机制:先让 parent(父)类加载器 寻找,只有在 parent 找不到的时候才从本人的类门路中去寻找。
类加载还采纳了 cache 机制:如果 cache 中保留了这个 Class 就间接返回它,如果没有才从文件中读取和转换成 Class,并存入 cache,这就是为什么批改了 Class 然而必须重新启动 JVM 能力失效, 并且类只加载一次的起因。
自定义类加载器
创立了一个类 javax.activation.MimeType,在这个类中有一个办法 show(); 当 jvm 加载这个类时,因为在 rt.jar 包下也存在一个 MimeType 类,并且包名都一样,这时 jvm 就会应用疏导类加载器加载这个类,而咱们想得到的其实是应该由利用类加载器加载的 Class.
解决方案: 自定义类加载器.
1. 创立一个类,去继承自 ClassLoader
2. 重写 findClass 办法,在这个办法中通过 defineClass 将一个.class 文件转换成 Class 对象.