带着你一步一步在Kotlin使用注解,让你不再害怕注解
2017-09-06 08:13
211 查看
背景知识:
Kotlin中有以下四种元注解(用来定义注解的注解):@Target:限定注解标记的目标(属性、方法、类、扩展等等)
@Retention:限定注解是否存储到字节码文件中;在运行时通过反射是否可见(默认情况下以上两个条件均为真)
@Repeatable:允许在同一个元素上重复使用同一个注解
@MustBeDocumented:指定该注解是公有 API 的一部分,并且应该包含在生成的 API 文档中显示的类或方法的签名中。
在Kotlin中定义一个注解类,需要使用 annotation 关键字:
@Target(AnnotationTarget.PROPERTY) annotation class Valid
实际操作
说明:此次实例是对Spring框架中的Value注解进行简单的实现。大致的运行过程可以概括成这样:在某个类中为它的属性添加@Value(value="key")注解,在配置文件中为注解中出现的关键字赋予相应的值。最终通过注解解析器将配置文件中的值注入到添加了注解的属性中。
第一步:定义注解
说明:我们所定义的是一个属性层级的注解,并且需要在运行时获取注解的相关信息,注解含有一个String类型的参数。最终注解定义的代码是这样子的:@Target(AnnotationTarget.PROPERTY) @Retention(AnnotationRetention.RUNTIME) //这一行也可以省略 annotation class Value(val value:String)
第二步:对注解进行解析
说明:注解的定义十分的简单,就那么几行代码。但你要想让注解真正的起作用,你还需要对注解进行相应的解析才行。在解析注解的过程中会使用到大量和反射有关的代码,对反射的概念不熟悉的同学,先去看看反射要不然看接下来的这些代码会蛮吃力的。class AnnotationExpression (val obj:Any){
fun expression(){ val clazz=obj::class clazz.declaredMemberProperties.forEach { prop-> val mutableProp= try{ prop as KMutableProperty<*> }catch (e:Exception){ null } ?: return@forEach mutableProp.annotations.forEach { annotation-> val propClassName=mutableProp.returnType.toString().removePrefix("kotlin.") when(propClassName) { in numtypeSet->mutableProp.setter.call(obj, (readProp(annotation as Value) as kotlin.String).toNum(propClassName)) "String"->mutableProp.setter.call(obj, (readProp(annotation as Value) as kotlin.String)) "Boolean"->mutableProp.setter.call(obj, (readProp(annotation as Value) as kotlin.String).toBoolean()) } } } }
通过KClass获取的KProperty1默认是不能被修改的,意味着你只能获取属性的值,而不能对其进行修改。所以在这里,我们对它进行了以下转换
prop as KMutableProperty<*>
因为可能出现使用该注解注释val变量的情况,在这里还进行了异常捕获,当发生异常时,直接跳过接下来的处理过程。
我们可以看到上面的代码中多次出现了 readProp 函数,在这里这个函数的作用是根据注解的信息,从配置文件中读取相应的数据。
private fun readProp(value:Value): Any? { val prop=Properties() prop.load( AnnotationExpression::class.java.getResource("app.properties").openStream()) return prop.get(value.value) }
# app.properties name="feint" age=11 money=13.5 gender=true
由于直接从property中获取的类型可能会和使用了@Value注解的属性的类型不匹配,因此我们需要根据属性的类型对从配置中获取的类型进行转换。
在这里适配了,布尔型、字符串型以及数字型的数据。由于数字型的类别特别多(Int,Double,Byte等等),便专门为String扩展了一个 toNum 函数,它接受一个String类型的参数,表示类型的名称。具体的代码是下面这样子的:
fun String.toNum(className:String):Any{ val clazz=Class.forName("java.lang.${typeMap[className]}") return clazz.getMethod("parse$className",String::class.java).invoke(null,this) }
这个地方又有一个坑,我本来是想通过反射调用Kotlin的String类中类似toInt、toDouble的方法。可是,运行后竟然提示,Kotlin的内置类型目前对反射的支持还不完善。。。无奈只好使用Java中那些包装类的parse方法。
第三步:使用注解
说明:使用的过程也没啥好说的,直接上代码class User{ @Value(value = "name") lateinit var name:String @Value(value = "age") var age:Int=0 @Value(value = "money") var money:Double=0.0 @Value(value = "gender") var gender:Boolean=false override fun toString(): String { return "(name:$name; age:$age; money:$money; gender:${if(gender) "man" else "woman"})" } }
fun main(args: Array<String>) { val user=User() AnnotationExpression(user).expression() println(user.toString()) }
源码地址(Github):注解练习
欢迎关注Kotlin学习网
相关文章推荐
- 一步一步深入spring(5)--使用基于注解的spring实现 AOP
- Code Fragment-不再建议使用的方法,使用注解说明。
- kotlin使用Parcelize注解简化Parcelable的书写
- Spring 使用注解方式进行事务管理
- 一步一步使用LiveWriter 在CSDN上写日志
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- 在Android中使用枚举注解而不是枚举
- google注解@SerializedName的使用说明
- 基于注解的Spring AOP的配置和使用
- 使用Kotlin开发Android应用(I):简介
- Android:使用ButterKnife注解绑定控件后报NullPointException
- 使用spring @Scheduled注解执行定时任务、
- SpringMVC_配置和注解--跟海涛学SpringMVC(和自己在项目中的实际使用的对比)
- 基于注解的Spring多数据源配置和使用
- Hibernate注解使用方法总结
- guava中eventbus注解使用
- Java注解的使用
- 一步一步学ios UILabel(label控件)的详细使用及特殊效果(五5.6)
- Android注解使用之注解编译android-apt如何切换到annotationProcessor
- 如何在Android Studio中使用Kotlin开发app