黑马程序员_java学习日记_Java高新技术_类加载器和代理

--------------------- android培训java培训java学习型技术博客、期待与您交流! ----------------------

类加载器:加载类的工具,

一个类中出现了一个类的名字,java虚拟机首先把该类的字节码加载进内存,

Java虚拟机可以安装多个类加载器,每个加载器加载不同位置的类,一般用到的类加载器有三个bootstrap,extclassloader,appclassloader

类加载器也是java类,也是靠别的类加载器(bootstrap)加载bootstrap是嵌套在java虚拟机内核里面

范围

Boot

Ext:

App:classpath指定的jar或目录

//得到类加载器的类

       System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());

       //system类是由C写的类加载器加载的

       System.out.println(System.class.getClassLoader());

       /**

        * 类加载器的树状结构

        * boot

        *  |--ext

        *      |--app

        */

       ClassLoader loader = ClassLoaderTest.class.getClassLoader();

       while(loader != null)

       {

           System.out.println(loader.getClass().getName());

           loader = loader.getParent();

       }

       System.out.println(loader);

如果两个类加载器都可以加载同一个类文件,则有父级加载这是类加载器的委托机制

首先派当前线程的类加载器去加载第一个类

如果类A中引用了B类,则该类加载器继续加载

还可以通过ClassLoader.loadClass()方法去加载

先向上级类推脱,一直推脱到Boot,然后各个类加载器在自己的范围内查找,如果能找到则下级就不再寻找直接用,这样可以避免一个类被多次加载

自己写一个类加载器加载java.lang.System

编写自己的类加载器

模板方法设计模式:父类有一个方法,不管哪个子类,

首先自定义一个类加载器,继承app,指定加载路径

继承classloader

通过loadclass方法让父类去加载该类文件,如果加载不了则自己加载(该流程固定,但是细节由子类完成)

重写findclass方法

调用define方法返回class字节码

Tomcat启动之后,java虚拟机中会有很多的类加载器

Tomcat是由java虚拟机启动的

代理

代理类的每个方法与目标类的方法一样,而且代理类的方法必须去调用目标类的方法然后再加上自己的功能,

面向切面编程AOP

将交叉业务模块化

Java虚拟机可以再运行期间动态生成类的字节码文件,这种动态生成的类往往被用作代理类,即动态代理类

生成的动态代理类必须继承一个或多个接口,所以动态代理类只能用作具有相同接口的类的目标类的代理

Cglib可以动态生成一个类的子类,该子类也可以用作代理类

添加系统功能代码的位置

调用方法之前

调用方法之后

调用方法前后

Catch块中

单线程用stringbuilder

多线程用stringbuffer

java虚拟机创建动态类及实例对象需要提供的信息

生成的类有哪些方法,通过让其实现的哪些接口的方式进行告知

产生的类字节码必须有一个关联的类加载器对象

生成的类中的方法时怎么样的也得由我们提供,把我们写的代码

或者通过newProxyInstance一步到位

publicclass test01 {

 

    /**

     * @param args

     */

    publicstaticvoid main(String[] args) {

       Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

       Constructor[] method = clazz.getConstructors();

       StringBuilder sb = new StringBuilder(clazz.getName());

       for(Constructor m : method)

       {

           //sb.append(c.getName());

           Class[] parm = m.getParameterTypes();

           for(Class cla : parm)

           {

              sb.append(cla.getSimpleName());

           }

       System.out.println(sb.toString());

       }

       try {

           //创建一个构造器对象传递的参数为该构造参数的类字节码

           Constructor c =clazz.getConstructor(InvocationHandler.class);

           //创建对象

           Collection coll = (Collection)c.newInstance(new myInvocationHandler());

           System.out.println(coll.toString());

           coll.clear();//清除集合

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

 

}

class myInvocationHandler implements InvocationHandler

{

 

    @Override

    public Object invoke(Object arg0, Method arg1, Object[] arg2)

           throws Throwable {

       returnnull;

    }

}

原理:

调用invoke方法涉及的三个要素:调用哪个对象,调用对象的哪个方法,方法的参数

AOP:作用的目标和将要执行的代码可以作为对象传递进去

你可能感兴趣的:(黑马程序员_java学习日记_Java高新技术_类加载器和代理)