• 类的加载和反射


    一、类的加载

      类的加载一共分为三步:

      1、加载

          就是将类加载进内存,并同时创建一个Class对象(就是描述一个 .class 文件的对象)
          而且任何类被使用前都会先创建一个 Class对象

      2、连接

          验证 是否有正确的内部结构,并和其他类协调一致
          准备 负责为类的静态成员分配内存,并设置默认初始化值
          解析 将类的二进制数据中的符号引用替换为直接引用

      3、初始化

          见前面的初始化笔记。

        初始化的时机:

            创建类的实例
            访问类的静态变量,或者为静态变量赋值
            调用类的静态方法
            使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
            初始化某个类的子类
            直接使用java.exe命令来运行某个主类



    二、类的加载器

      类加载器
        负责将.class文件加载到内在中,并为之生成对应的Class对象。

      类加载器的组成

        1、Bootstrap ClassLoader 根类加载器

            也被称为引导类加载器,负责Java核心类的加载
          比如: System,String等。在JDK中JRE的lib目录下rt.jar文件中


        2、Extension ClassLoader 扩展类加载器

            负责JRE的扩展目录中jar包的加载。
          在JDK中JRE的lib目录下ext目录


        3、Sysetm ClassLoader 系统类加载器

            负责在JVM启动时加载来自java命令的class文件,
            以及classpath环境变量所指定的jar包和类路径
          (一般此加载器加载的就是我们所写的文件)


    三、反射

      概念:
          JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
          对于任意一个对象,都能够调用它的任意一个方法和属性;
          这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

        就是通过一定的方法(如:通过 .class文件的文件名)来指向一个 .class文件,在获得一个用来
        描述这个 .class文件的 Class 对象,

        之后通过该Class对象来获取文件中的 构造方法、成员变量、成员方法, (既可以批量获取,
        也可以单个获取,既可以获取public 类型的,也可获取private类型的, 甚至可以通过暴力访问的方法
        来访问 private的成员。)

        通过获取到的构造方法,可以得到一个Object型的该类对象,(Constructer)
        通过获取到的成员 和 该类对象,可以操作.class文件中的成员了。(Field, Method)

      获取Class对象:
              1、Object的 getClass 方法。
              2、数据类型的静态属性 class (引用类型、基本类型)。
              3、Class类中的静态方法。
                  static Class<?> forName(String className)
                  static Class<?> forName(String name, boolean initialize, ClassLoader loader)

      获取构造方法:

            获取构造方法
              getConstructors(Class<?>... parameterTypes)
              getDeclaredConstructors()
            创建对象
              newInstance()
              con.newInstance(“zhangsan", 20);



            获取成员变量:
                获取所有成员
                      getFields,
                      getDeclaredFields
                获取单个成员
                      getField,
                      getDeclaredField
                修改成员的值
                      set(Object obj,Object value)
                      将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

            获取成员方法:
                获取所有方法
                      getMethods      获取所有的public成员变量(自己的和父类的)
                      getDeclaredMethods  获取只属于自己的所有的变量。
                获取单个方法
                      getMethod
                      getDeclaredMethod
                暴力访问
                      method.setAccessible(true);


    四、动态代理

        动态代理:   在程序运行过程中产生的这个对象
                而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,
              所以,动态代理其实就是通过反射来生成一个代理

          就是说,我们需要对一个我们已有的对象的方法添加一些新的功能,而这些功能对每个对象、
          每个方法都是相同的, 那么我们就可以使用动态代理来获得一个该对象的动态代理对象,
          使用该对象再调用的方法,就是被动态代理过后的方法。


        在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,
        通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。
        我们有更强大的代理cglib


        Proxy类中的方法创建动态代理类对象
          public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

        最终会调用InvocationHandler的方法
            InvocationHandler
            Object invoke(Object proxy,Method method,Object[] args)

     1 public class MyBeanFactory {
     2     
     3     public static UserService createService(){
     4         //1 目标类
     5         final UserService userService = new UserServiceImpl();
     6         //2切面类
     7         final MyAspect myAspect = new MyAspect();
     8         /* 3 代理类:将目标类(切入点)和 切面类(通知) 结合 --> 切面
     9          *     Proxy.newProxyInstance
    10          *         参数1:loader ,类加载器,动态代理类 运行时创建,任何类都需要类加载器将其加载到内存。
    11          *             一般情况:当前类.class.getClassLoader();
    12          *                     目标类实例.getClass().get...
    13          *         参数2:Class[] interfaces 代理类需要实现的所有接口
    14          *             方式1:目标类实例.getClass().getInterfaces()  ;注意:只能获得自己接口,不能获得父元素接口
    15          *             方式2:new Class[]{UserService.class}   
    16          *             例如:jdbc 驱动  --> DriverManager  获得接口 Connection
    17          *         参数3:InvocationHandler  处理类,接口,必须进行实现类,一般采用匿名内部
    18          *             提供 invoke 方法,代理类的每一个方法执行时,都将调用一次invoke
    19          *                 参数31:Object proxy :代理对象
    20          *                 参数32:Method method : 代理对象当前执行的方法的描述对象(反射)
    21          *                     执行方法名:method.getName()
    22          *                     执行方法:method.invoke(对象,实际参数)
    23          *                 参数33:Object[] args :方法实际参数
    24          * 
    25          */
    26         UserService proxService = (UserService)Proxy.newProxyInstance(
    27                                 MyBeanFactory.class.getClassLoader(), 
    28                                 userService.getClass().getInterfaces(), 
    29                                 new InvocationHandler() {
    30                                     
    31                                     @Override
    32                                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    33                                         
    34                                         //前执行
    35                                         myAspect.before();
    36                                         
    37                                         //执行目标类的方法
    38                                         Object obj = method.invoke(userService, args);
    39                                         
    40                                         //后执行
    41                                         myAspect.after();
    42                                         
    43                                         return obj;
    44                                     }
    45                                 });
    46         
    47         return proxService;
    48     }
    49 
    50 }
    JDK proxy
     1 public class MyBeanFactory {
     2     
     3     public static UserServiceImpl createService(){
     4         //1 目标类
     5         final UserServiceImpl userService = new UserServiceImpl();
     6         //2切面类
     7         final MyAspect myAspect = new MyAspect();
     8         // 3.代理类 ,采用cglib,底层创建目标类的子类
     9         //3.1 核心类
    10         Enhancer enhancer = new Enhancer();
    11         //3.2 确定父类
    12         enhancer.setSuperclass(userService.getClass());
    13         /* 3.3 设置回调函数 , MethodInterceptor接口 等效 jdk InvocationHandler接口
    14          *     intercept() 等效 jdk  invoke()
    15          *         参数1、参数2、参数3:以invoke一样
    16          *         参数4:methodProxy 方法的代理
    17          *         
    18          * 
    19          */
    20         enhancer.setCallback(new MethodInterceptor(){
    21 
    22             @Override
    23             public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    24                 
    25                 //
    26                 myAspect.before();
    27                 
    28                 //执行目标类的方法
    29                 Object obj = method.invoke(userService, args);
    30                 // * 执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
    31                 methodProxy.invokeSuper(proxy, args);
    32                 
    33                 //
    34                 myAspect.after();
    35                 
    36                 return obj;
    37             }
    38         });
    39         //3.4 创建代理
    40         UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
    41         
    42         return proxService;
    43     }
    44 
    45 }
    Cglib proxy

    五、属性描述器

        BeanInfo :一个描述对象的类

        PropertyDiscriptor:属性描述器(获得某个对象的某个属性的描述器)

        pd.setReadMethod():得到set属性(返回Method)

        m.invoke(对象,值):为该对象该属性赋值

    六、内省

        BeanUtils.setProperty(对象,属性,值):给该对象的该属性复制(8种基本数据类型可以互相转换,get类似)

        BeanUtils.populate(对象名,Map集合):通过一个Map集合中的数据为对象中的所有属性赋值

        ConvertUtils.register(Convert,要装换成的数据类型);类型转换器

          Convert:接口,下有各种转换对象:DateLocalConvert等。

  • 相关阅读:
    mysql 查询优化
    图解Java常用数据结构(一)
    mybatis 详解(五)------动态SQL
    Mybatis的ResultMap的使用
    java系统变慢的优化简略步骤
    mysql基本操作
    mysql数据库的优化 一
    tomcat的启动启动与关闭
    vueJs的简单入门以及基础语法
    Oracle常用命令-用户、表空间、赋权限、导入导出
  • 原文地址:https://www.cnblogs.com/soficircle/p/6771539.html
Copyright © 2020-2023  润新知