动态代理模式原理之反射动态加载技术
Hello,大家好!我又来了,最近工作一直在忙于USB外接打印机接入速度高性能优化。从刚开始的接入到打印40s时长,极致性能优化到15s~19s时长,期间踩了不少吭最终达到理想效果。哎呀,话题扯的远了。前几天,一个小伙伴说:元哥,我在代码里老是看到 invoke() 这个方法,就是反射时候用到的,这是到底是干嘛的呀??正好我这几天在优化时,有阅读到底层源码里,用到动态代理。所以呢决定来写写,巩固一下知识,总结一下。
好啦,
本文主要通过以下几个部分来写
1.什么是反射,反射的用途?
引用官方文档的原话
Reflection
Reflection is a set of language and library features that allows for introspecting the structure of your own program at runtime.
意思大概是说,反射是一组语言和库特性,允许在运行时反思自己程序的结构。
读者:我嚓,你要不要这样,你这么直白的翻译,怎么一脸蒙呢。
作者:哈哈哈,被你说中了。别急请听我用简单的话来讲,一切简单话
反射,简单来讲,就是一开始并不清楚,不知道我们要去初始化的类是什么?
像平时我们在使用一个对象时,我们明确清楚要去怎么初始化对象,如:
正:val person = Person()
而我们反射呢,体现在一个“反” 上面。
反射就是在运行时才知道我们要操作的类是什么,包括获取类的构造,使用类的成员方法等等
反射的用途
举几个例子
-
通过反射去调用其类的私有方法.。
-
设计框架时为了扩展 使用反射。
-
通过反射配合注解实现APT技术。
。。。
。。。 装逼,喜欢搞逼格高的代码!
用途很多
2.反射的常用手段
这里我们简单起见呢,首先就定义一个类,用于测试。类如下:
/**
* @description 描述人,用于验证反射
* @author 陈元
* @date 2020 07/14
*/
class Person {
lateinit var name: String
var age: Int = 0
constructor()
constructor(name: String, age: Int){
this.name = name
this.age = age
}
private var address = "南京市蓬莱仙岛"
var doing = "练习反射,为动态代理的原理作准备!"
private fun speakLanguage(name: String = "吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮") {
println("南京人说:$name")
}
fun goodFood() {
println("南京正宗桂花鸭")
}
fun sayAddress(){
println(address)
}
var lambdaTest: (() -> Unit)? = null
}
这里呢,基本我们上平时写的类的结构都有了,什么构造器呀,有参的,无参的,公开方法,私有方法,私有字段,公开字段 等等。
我们说,一切皆对象!我们的class 也一样,也有一个专门的保存类的结构化信息的Class对象
1.获取类的Class对象,我们JDK为我们提供了三种方式。
示例:
/**
* description: 反射初级用法
* author: 陈元
* data:2020/7/21
*/
fun main() {
/**
* class对象 获取方式一,通过 类的完整包名
*/
val personClass = Class.forName("com.myapplication.Person")
println(personClass)
val personal = Person("刘亦菲", 18)
/**
* class对象 获取方式二,通过 javaClass
*/
val personClass1 = personal.javaClass
println(personClass1)
/**
* Class对象 获取方式三,通过 类名::class.java
*/
val personClass2 = Person::class.java
println(personClass2)
通过反射获取构造器
/**
* 通过反射获取Person的实例对象,无参的
*/
val person1 = getPerson(personClass as Class<Person>)
println(person1)
/**
* 通过反射获取Person的实例对象,带参数的
*/
val person2 = getPerson1(personClass1,"周芷若",18)
val person3 = getPerson1(personClass2,"赵敏",18)
通过反射获取方法
示例:
/**
* 反射获取类的方法,包括父类的方法
*/
personClass.methods.forEach {
println(it.name)
}
println("_____________ 疑问? 为啥打印出来没有私有方法呢?? 原来需要使用declared _______________________")
/**
/**
* 反射获取类的自身的所有方法
*/
personClass.declaredMethods.forEach {
println(it.name)
}
结果:
这里包括父类的wait notify 等等方法都能获取到。
getName
setName
sayAddress
getDoing
setAge
getLambdaTest
setDoing
getAge
setLambdaTest
goodFood
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
____________________________________
getName
setName
sayAddress
getDoing
speakLanguage
speakLanguage$default
setAge
getLambdaTest
setDoing
getAge
setLambdaTest
goodFood
setLambadaTest方法 哪来的??
哎,兄弟。请看,这就是呀,在我们kotlin里面函数可以类似于前端写的ES6一样,函数声明
var lambdaTest: (() -> Unit)? = null
哦,这样啊。
还可以获取属性,这里就简单提一下
/**
* 反射获取类的自身所有属性 成员变量
*/
personClass