(一) 类加载器
Java的类加载机制:
(1)首先加载第一个类加载器,它不是Java类,叫做BookStrap,但是它的加载范围在JRE/lib/rt.jar里;
(2)第二个类加载器,它是Java类,叫做ExtClassLoader,它的加载范围在JRE/lib/ext/*.jar里;
(3)第三个类加载器,它是Java类,叫做AppClassLoader,它的加载范围在ClassPath指定的所有jar或目录里;
(4)自定义的类加载器,继承ClassLoader抽象类,覆盖父类中的findClass方法,加载指定的Java类。
注意:
每个类加载器加载类时,有先委托给其上级类加载器,所以加载顺序是1234,加载不到则抛出ClassNotFoundException异常;
如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B;
可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
(二)代理
(1)AOP(Aspect Oriented Program):面向切面(方面)编程
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理,日志,计算方法的运行时间,事务管理等等;
代理类与目标类有相同接口,它的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
(2)在代理方法中的如下四个位置加上系统功能代码:
在调用目标方法之前;在调用目标方法之后; 在调用目标方法前后; 在处理目标方法异常的catch块中。
(3)动态代理类:jvm可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类。
(4)CGLIB库
可以动态生成一个类的子类,一个类的子类也可以用作该类的代理。
(5)
代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
(在调用目标方法之前:在调用目标方法之后:在调用目标方法前后:在处理目标方法异常的catch块中)。
(6)创建动态类及查看其方法列表信息
Class classProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
(7)创建动态类的实例对象及调用其方法
Constructor constructor = classProxy1.getConstructor(InvocationHandler.class);
class InvocationHandler1 implements InvocationHandler{
public Object invoke(...){...}
}
Collection proxy1 = (Collection)constructor.newInstance(new InvocationHandler1());
(8)完成InvocationHandler对象的内部功能
Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){
public Object invoke(...){...}
})
Collection proxy3 = (Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler(){
ArrayList target = new ArrayList();
public Object invoke(Object proxy,Method method,Object[] args)
throws Throwable{
long beginTime = System.currentTimeMillis();
Object retVel =method.invoke(target,args);
long endTime = System.currentTimeMillis();
System.out.print(method.getName()+"running time of"+(endTime - beginTime));
return retVel;
}
}
)