反射和代理

一、反射

1、概述

反射是允许在运行态动态生成Object对象,能够通过类Class信息获取属性、方法、注解,并能够动态调用,能够动态调用对象方法的机制。

2、获取Class对象

通过以下方式获取到Class对象:

  1. 通过对象的getClass()方法。
  2. 通过类的class成员变量。
  3. 通过Class类的forName()方法。
Student student = new Student();
//1. 通过对象的getClass()方法。
Class<? extends Student> clazz = student.getClass();
//2. 通过类的class成员变量。
Class<Student> clazz1 = Student.class;
//3. 通过Class类的forName()方法。
Class<?> clazz2 = Class.forName("reflect.reflect.Student");

3、创建对象

通过以下方式创建对象:

//调用方法:clazz.newInstance()
Student student1 = clazz.newInstance();

//获取构造器后调用方法:constructor.newInstance()
Constructor<? extends Student> constructor = clazz.getConstructor();
Student student2 = constructor.newInstance();

通过以下方式获取属性、方法和注解:

//获取属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

//获取方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
    System.out.println(method.getName());
    Class<?>[] types = method.getParameterTypes();
    if (types != null && types.length > 0) {
        System.out.println(types[0].getName());
    }
}

//获取注解
Annotation[] annotations = clazz.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
    System.out.println(annotation.annotationType().getSimpleName());
}

4、总结

反射的优点:

  1. 能够再运行态动态获取类的属性、方法和注解信息,能够动态生成对象。

反射的缺点:

  1. 破坏了类的封装性,通过反射能够读取private的属性、方法。

二、代理

代理是一种设计模式,作用是在不扩张目标对象的前提下,通过扩展代理类来对目标对象的功能进行增强。其模型为访问者通过代理对象来访问目标对象。一般包括代理对象、目标对象、目标对象接口三种角色。
在这里插入图片描述

1、静态代理

静态代理是在编译期就已经在代理类中确定了目标对象要扩展的功能,无法在运行态动态生成代理对象,灵活性不够。

代码实现​ https://github.com/yangnk/JavaHelloworld/tree/master/src/main/java/reflect/proxy

2、动态代理

动态代理可以在运行态动态生成代理对象,适用于在运行态目标对象会灵活生成的。

(1)JDK原生动态代理
  • 实现方法:原生的JDK动态代理重点是实现InvocationHandler接口,需要你重写invoke()方法,在这个方法里将需要增强的部分增强就好了。
  • 实现原理:通过Proxy.newProxyInstance()方法创建实现InvocationHandler接口的invoke()方法,底层是通过反射来做到的。
(2)CgLib动态代理
  • 实现方法:这个是第三方lib实现,需要引入cglib库,首先还是需要实现MethodInterceptor接口,重写其中的intercepter()方法,这个看起来和JDK 原生动态代理差不多。
(3)总结

JDK动态代理和CgLib动态代理区别:

  1. JDK Proxy在原生JDK中即可实现,通过实现InvocationHandler接口即可,他的原理是通过反射生成目标类的匿名类;而CgLib Proxy需要引入第三方包,他是通过asm来操作字节码,生成目标类的子类,在运行时将该子类的字节码加载进来。
  2. JDK proxy作为代理类,需要目标类有接口才能代理实现,即只能针对接口才能生成代理类;CgLib Proxy不需要目标类有接口就能代理实现。

参考文献

  1. Java三种代理模式:静态代理、动态代理和cglib代理:https://segmentfault.com/a/1190000011291179
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yangnk42

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值