java类加载器,代理类以及Aop深入剖析
一、类加载器及其委托机制的深入分析: java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个负责加载特定位置的类: 加载器名: BootStrap、 ExtClassLoader、 AppClassLoader 对应管辖范围:JRE/lib/rt.jar、Jre/lib/ext/*.jar、CLASSPATH指定目录的所有jar或目录 类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。
java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类的装载器对象时,需要为其制定一个父级类装载器对象或默认采用系统类装载器为其父类加载。
类加载器的委托机制: 当java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢? 1、首先当线程的类加载器去加载线程中的第一个类。 2、如果类A中引用的类B,java虚拟机将使用加载类A的类装载器来加载类B。 3、还可以直接调用ClassLoader.loadClass()方法来指定某个加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。 当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出ClassNotFoundException,不是再取找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多少儿子,找哪个呢?
自定义类加载器的编写原理分析: 写自己的类加载器,字节的类加载器覆盖findClass(),就可以获取到对应的字节码,将这些字节码交给definClass()方法将其变成Class对象。
模板方法设计模式 父类-->loadClass/findClass()/得到Class文件转换成字节码-->definClass()把自己数组变成Class 子类1(自己干) 子类2(自己干) 总体流程在父类规定好,子类继承父类方法,父类定义局部细节为抽象方法,子类填写对应抽象方法,流程在父类中已经规定好。
编写对class文件进行加密的工具类: 编写和测试自己编写的解密类加载器: 类加载器的一个高级问题的实验分析:
二、分析代理类的作用与原理及AOP概念
什么是代理: 要为已存在的多个具有相同接口的目标类各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、实物管理、等等。 代理原理可以理解为, 代理类(代理类中的方法为调用目标类中方法并扩展)和目标类实现同一个接口,客户端调用程序直接对接口操作。
AOP(Aspect Oriented Program面向方面的变成): 交叉业务:安全、实物、日志等功能要贯穿到好多个模块中。 AOP的目标就是要使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果一样。
AOP
1. 系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,如下所示:
安全 事务 日志
a) Student Service ----------|-----------|----------|----------
b) CourseService ----------|-----------|----------|----------
c) MiscService ------------|-----------|----------|----------
2. 用具体的程序代码描述交叉业务:
a) method1 method2 method3
b) { { {
c) ------------------------------------------------切面
d) ------ -------- ------
e) ------------------------------------------------切面
f) } } }
3. 交叉业务的编程问题即为面向方面的编程(Aspect oiented program ,简称AOP),AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。如下所示:
a) --------------------------------------------------切面
b) func1 func2 func3
c) { { {
d) --- --- ---
e) } } }
f) -------------------------------------------------切面
4. 使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
动态代理技术: JVM可以在运行期动态生成出类的字节码,这种动态生成类旺旺被用作代理类,即动态代理类。 JVM生成的动态类必须实现一个或多个接口,所以JVM生成的动态类只能用作具有相同接口的目标类和代理。 CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。 代理类的各个方法中通常除了要调用目标和相应方法对外返回目标返回结果外,还可以在代理方法中的如下四个位置加上系统功能代码: 1、在调用目标方法之前 2、在调用目标方法之后 3、在调用目标方法前后 4、在处理目标方法异常的catch块中
创建动态类及查看其方法列表信息: 创建动态类的实例对象及调用其方法: 完成InvocationHandler对象的内部功能: 分析InvocationHandler对象的运行原理: 动态类生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和一个如下接受InvocationHandler参数的构造方法。 总结分析动态代理类的设计原理与结构: 运行原理: 客户端调用代理,代理的构造方法接受一个Handler,客户端调用代理的各个方法,代理各个方法将调用请求转给handler对象的invoke方法(可以添加新的方法),handler将对应请求分发给对应目标的相应请求。 把需要的功能封装成对象,即把切面你的代码封装成对象,以对象的形式传递,并执行对象就等于执行了切面的代码。 编写可生成代理和插入通告的通用方法: 实现类似spring的可配置的AOP框架:
工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。 BeanFactory的构造方法接受代表配置文件的输入流对象,配置文件格式如下: #xxx=java.util,ArrayList xxx=cn.itcast.ProxyFactoryBean xxx.target=java.util.ArrayList xxx.advice=cn.itcast.MyAdvice