单元测试 反射 注解 动态代理

单元测试

为什么单元测试要叫单元测试

单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试。

如何实现单元测试

  1. 必须导入Junit框架的jar包
    在这里插入图片描述

  2. 定义的测试方法必须是无参数无返回值,且公开的方法。

  3. 测试方法使用@Test注解标记。

Junit4.x.x 常用注解

@Before 常用于初始化资源
@After 常用于释放资源
在这里插入图片描述

反射

反射有什么用

反射,可以让我们在类运行的时候,直接获取类的信息和类的成分,如构造器对象、成员变量对象、成员方法对象

反射的原理是什么

.java 文件编译后会变成 .class 字节码文件,这时获得这个 class 文件,就可以得到解析出class 的所有成分

在这里插入图片描述

什么是Class 类对象

Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI。
这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建
也就是说:

  1. Class类也是类的一种,只是名字和class关键字高度相似。Java是大小写敏感的语言。
  2. Class类的对象内容是你创建的类的类型信息,比如你创建一个shapes类,那么,Java会生成一个内容是shapes的Class类的对象
  3. Class类的对象不能像普通类一样,以 new shapes() 的方式创建,它的对象只能由JVM创建,因为这个类没有public构造函数
  4. Class类的作用是运行时提供或获得某个对象的类型信息,和C++中的typeid()函数类似。这些信息也可用于反射。

反射的第一步是获取 Class 对象,那么如何获取

方式一:Class c1 = Class.forName(“全类名”);//静态初始化
方式二:Class c2 = 类名.class//不初始化
方式三:Class c3 = 对象.getClass();//静态初始化 + 非静态初始化

利用反射获取构造器的 API在这里插入图片描述

利用反射得到的构造器可以用来干什么

创建对象
public newInstance(Object… initargs)

如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象
setAccessible(boolean)

利用反射获得成员变量的 API

在这里插入图片描述

利用反射获得的成员变量可以做什么

用于取值、赋值
在这里插入图片描述
如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
setAccessible(boolean)

利用反射获得成员方法的API

在这里插入图片描述

利用反射获得的成员方法对象可以做什么

可以触发执行这个方法
在这里插入图片描述如果某成员方法是非public的,需要打开权限(暴力反射),然后再触发执行
setAccessible(boolean)

反射为何可以给约定了泛型的集合存入其他类型的元素

  • 编译成Class文件进入运行阶段的时候,泛型会自动擦除。
  • 反射是作用在运行时的技术,此时已经不存在泛型了

反射的作用

  1. 可以在运行时获得一个类的全部成分,进行操作
  2. 可以破坏封装性(无视访问权限,直接获取成分)
  3. 可以破坏泛型的约束性(泛型只在编译结算会约束类型,编译完,class文件中就会进行类型擦除,运行时,直接获得集合元素,可以无视类型,添加任意元素)
  4. 用于做高级框架(无视类的成员类型、有哪几个成员,直接遍历操作)

注解

自定义注解如何生效

注解只是有标记作用。
自定义一个注解,然后利用反射获取对象上方的注解,如果为自定义的注解,就进行业务操作。

如何自定义注解

属性值就是想要用户输入的参数
在这里插入图片描述
还需要加上元注解

value 属性有什么特别之处

value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写!!
但是如果有多个属性, 且多个属性没有默认值,那么value名称是不能省略的

元注解有哪些

常用的是 @Target 和 @Retention
@Target 说明自定义的注解可以用在什么对象上

  • TYPE,类,接口
  • FIELD, 成员变量
  • METHOD, 成员方法
  • PARAMETER, 方法参数
  • CONSTRUCTOR, 构造器
  • LOCAL_VARIABLE, 局部变量

@Retention 注解说明自定义注解的生命周期

  • SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
  • CLASS: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
  • RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)

注解如何解析,注解输入的参数如何取出

  1. 注解@Target 在什么成分上,就先利用反射获得那个成分对象。比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解。
  2. 获得对象上的注解,使用 getDeclaredAnnotation
  3. 获得注解的属性值,并进行业务处理
    在这里插入图片描述

动态代理

什么是动态代理

为一个目标对象,创建代理对象,代理对象的业务逻辑包括了目标对象,并且在那基础上进行功能增强。

静态代理和动态代理如何实现

静态代理
比如原本是 A.class AImpl.class 中的 a() 方法,我想在 a() 方法前后增加一些记录时间的功能,则可以使用静态代理

  1. 直接实现 A.class
  2. 将 AImpl() 作为成员变量
  3. 实现 a(),代码为
    {
    记录时间;
    aimpl.a();
    记录时间;
    }
    将方法包裹起来

动态代理
当扩展 A 接口中的方法时,代理类也需要更改,这样很不方便,于是衍生出动态代理,利用反射,遍历接口中的每个方法,并增强每个方法
具体示例:
https://www.yisu.com/zixun/770726.html

动态代理在实际项目中有什么用

可以用于记录日志,监控性能,权限控制,缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 ),事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值