从反射到框架实现原理

反射(Class对象)

框架设计的灵魂 框架是半成品软件,简化编码

概念:将类的各个组成部分封装为其他对象,就是反射机制

Java代码:三个阶段:

1、第一阶段:Source源代码阶段:代码在磁盘上 .java类文件 ------>.class字节码文件

2、第二阶段:Class类对象阶段:ClassLoader类加载器,将字节码文件加载到内存:Class类对象:Fiilds对象,Constructor对象,Method对象

3、第三阶段:Runtime运行时阶段:new 类();

优点:1、可以在程序运行过程中,操作这些对象

​ 2、解耦代码

获取Class对象的方式

Class对象只有一个也即是 .class字节码文件只会加载一次

1、对于第一阶段:Class.forname(“全类名”);将字节码文件加载到内存里,返回Class对象

​ - 多用于配置文件,将类名定义在配置文件中,读取文件,来加载类

2、对于第二阶段:类名.Class:通过类名的属性class获取

​ - 多用于参数的传递

3、第三阶段:对象。getClass();该方法在Object中定义,故所有对象都有该方法

​ - 多用于对象的获取字节码的方式

tips:ClassNotFoundException一般都是类名写错了

Class对象的功能

  • 获取功能
    • 获取成员变量们:getFields():等方法
      • set设置值
      • get获取值
      • setAccessible(true):暴力反射,忽略访问权限修饰符的安全检测
    • 获取构造方法getConstructor等方法
      • 创建对象
        • T newInstance(Object… initargs初始化参数)
        • 如果使用空参构造方法创建对象,操作可简化:Class对象的newInstance方法
    • 获取成员方法getMethods(),都是Method类对象
      • 执行方法
        • 方法.invoke(对象,Object… initargs)
        • getName()获取方法名
    • 获取类名
      • getName()

注解

概念:

- 注释:文字解释程序功能,给程序员看的
- 注解:也叫元数据    代码级别的说明,1.5后新特性,对程序元素进行说明注释,给程序看的

作用分类:

  • 编写文档:通过代码里标识的元数据生成文档(生成doc文档)
  • 代码分析:通过代码里标识的元数据对代码进行分析(使用反射)
  • 编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查(override)

主要使用其代码分析的功能:

使用注解

  • 预定义注解

    • @override
    • @Deprecated 已经过时的:建议弃用
    • @SuppressWarnings:压制警告:对该方法产生的警告,都进行忽略,参数All
  • 自定义注解

    • 格式

      元注解

      publi @inerface 注解名称{}

    public @interface MyAno{
        int age();
        String name() default "zhangsan";
    }
    
    • 本质:注解本质就是一个接口,该接口默认继承Annotation接口

    • 注解的属性:接口中可以定义的抽象方法

      • 属性的返回值类型:除了以下类型,其他都不行

        • 基本数据类型
        • String
        • 枚举
        • 注解
        • 以上类型的数组
      • 定义了属性,在使用时需要给属性赋值

        • 定义属性使用default关键字给属性默认初始化值,使用时不赋值
        • 只有一个属性需要赋值,并属性的名字式value,使用时则value可省略,直接定义值即可
        • 数组赋值时,值使用{}包裹
    • 元注解:用于描述注解的注解

      • @Target:注解可以使用的位置
        • TYPE
        • METHOD
        • FIELD
      • @Retention:注解可以存活到的阶段(三个阶段)注解被 保留 的阶段
        • SOURCE
        • CLASS
        • RUNTIME
      • @Documented:注解是否被抽取到api文档
      • @Inherited:描述注解是否被子类继承
    • 解析注解:使用注解中定义的属性

      注解替换配置文件

      public class Demo{
      	public void show(){
              System.out.println("show running");
          }
      }
      
      @Target({ElementType.TYPE})
      @Tetention(RententPolicy.RUNTIME)
      public @interface Pro{
          String className();
          String methodName();
      }
      
      @Pro(className="com.mytest.Demo",methodName="show")
      public class ReflectTest{
          public static void main(Sring[] args){
              //解析注解
          	//获取该类的字节码文件
              Class<ReflectTest> reflectTestClass = ReflectTest.class;
              //通过具体的注解类名获取上边的注解对象(在这个大类的字节码文件中所有信息都有的)
              //在内存中生成了一个该注解接口的子类实现对象ProImpl,而且将响应的数据返回
              Pro an = reflectTestClass.getAnnotation(Pro.class);
              /*上边这个语句相当于
              	public class ProImpl implements Pro{
              		public String ClassName(){
              			return "com.mytest.Demo";
              		}
              		public String methodName(){
              			return "show";
              		}
              	}
              */
              //直接调用注解对象中的抽象方法,获取返回值
              String clsaaName = an.className();//获取到了数据"com.mytest.Demo"
              String methodName = an.methodName();
              
              //加载该类进内存
              Class cls = Class.forName(className);
              //创建对象
              Object obj = cls.newInstance();
              //获取方法对象
              Method method = cls.getMethod(methodName);
              //执行方法
              method.invlke(obj);
              
              
          }
      
      }
      
      • 总结

        • 1、获取注解定义的位置的对象(Class,Method,Field)

        • 2、获取指定的注解

          getAnnotation(注解.class)

          在内存中生成一个该注解接口的子类实现对象

        • 调用注解中的抽象方法获取配置的属性值

注解案例:简单的测试框架(框架的实现原理)

//要被测试的类,也就是要加@Chack测试注解的类
public class Calculator{
    //@Check
	public int add(){
        System.out.println(1+0);
    }
    //@Check
	public int sub(){
        System.out.println(1-0);
    }
    //@Check
	public int mul(){
        System.out.println(1*0);
    }
    //@Check
	public int div(){
        System.out.println(1/0);//这个是有异常的
    }
}
/*
	简单的测试框架
	对框架理解更深刻,框架就是一个可以运行的半成品软件(可以理解为解析程序),它运行起来帮助对主要的业务进行各种(注入等)操作
	、
	当主方法执行后,会自动自行被检测的所哟方法(加了check注解的方法),判断方法是否有异常,记录到文件中
*/
public class TestCheck{
    public static void main(String[] args){
        //创建计算器对象
        Calculator c = new Calculator();
        //获取字节码文件
        Class cls = c.getClass();
        //获取所有方法
        Method[] methods = cls.getMethods();
        
        int number = 0;//出现异常的次数
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));

        for(Method method : methods){
            //判断方法上是否有Check注解
            if(method.isAnnotationPresent(Check.class)){
                try{
                   method.invoke(c); //捕获执行方法时的异常
                }catch(Exception e){
                    //记录异常信息到文件中
                    number++;
                    bw.write(method.getName()+"方法出现异常了");
                    bw.newLine();
                    bw.write("异常的名称"+e.getCause().getSimpleName());
                    bw.newLine();
                    bw.write("异常的原因"+e.getCause().getMessage());
                    bw.newLine();
                    bw.write("------------------------");
                    bw.newLine();
                }
                
            }
        }
        bw.write("本次测试一共出现"+num+"次异常");
        bw.flush();
        bw.close();
        
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JSON序列化框架实现原理可以简单概括为以下几个步骤: 1. 对象解析:JSON序列化框架首先会对要序列化的对象进行解析,将对象的属性和对应的值提取出来。 2. 数据转换:接下来,框架会将解析得到的对象属性和值转换为JSON格式的数据。通常,这涉及将对象的属性名作为JSON键,将属性值转换为相应的JSON值。 3. 数据组装:将转换后的JSON数据按照一定的规则组装成一个字符串。这包括添加大括号、冒号、逗号等符号,以及字符串的引号。 4. 输出结果:最后,框架将组装好的JSON字符串输出,可以是写入文件、发送到网络或传递给调用者等。 具体实现细节可能因不同的JSON序列化框架而有所不同。不过,通常会使用一些工具类或算法来完成数据转换和组装的过程。例如,使用反射机制获取对象属性值,使用递归遍历对象的属性结构,使用字符串拼接或StringBuilder等方式来构建JSON字符串等。 一些高性能的JSON序列化框架还可能采用一些优化措施,如缓存对象结构、使用字节码生成技术、采用二进制协议等,以提高序列化和反序列化的效率。 总结来说,JSON序列化框架实现原理包括对象解析、数据转换、数据组装和输出结果等步骤。具体实现细节可能因不同的框架而有所不同,但一般会使用工具类、算法以及一些优化措施来完成序列化的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值