文章目录
前言
主要是说明一下java中的自定义注解 以及Java中的一些注解原理解释
参考了一些其他人的博客加上自己的理解
@interface
用来定义一个自定义注解 不是接口 是注解类 自动继承了java.lang.annotation.Annotation
接口。
在Java中,定义注解其实和定义接口差多不,只需要在interface前添加一个@符号就可以,即 @interface Zhujie{ },这就表明我们定义了一个名为 @Zhujie 的注解。
//自定义注解 @Zhujie ,该注解有两个元素 personId、company
public @interface Zhujie(){
int personId(); //元素1
String company() default "[unassigned]"; //元素2
}
在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
并且
Annotation
是所有注释类型的公共扩展接口。注意,手动扩展这个接口并不定义注释类型。还要注意,这个接口本身并不定义注释类型。
声明的注解允许作用于哪些节点使用@Target声明;保留级别由@Retention 声明。
一、@component注解为例
我们以spring中的@component注解为例,其格式如下所示
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default "";
}
1.继承的Annotation父接口
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
2.@Target中的参数ElementType
public enum ElementType {
TYPE, /* 类、接口(包括注释类型)或枚举声明 */
FIELD, /* 字段声明(包括枚举常量) */
METHOD, /* 方法声明 */
PARAMETER, /* 参数声明 */
CONSTRUCTOR, /* 构造方法声明 */
LOCAL_VARIABLE, /* 局部变量声明 */
ANNOTATION_TYPE, /* 注释类型声明 */
PACKAGE /* 包声明 */
}
3、@Retention中的参数RetentionPolicy
这是保留级别
public enum RetentionPolicy {
SOURCE, /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 */
CLASS, /* 编译器将Annotation存储于类对应的.class文件中。默认行为 */
RUNTIME /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}
4、成员变量
以无形参的方法形式来声明Annotation的成员变量,方法名和返回值定义了成员变量名称和类型。使用default关键字设置默认值,没设置默认值的变量则使用时必须提供,有默认值的变量使用时可以设置也可以不设置。
//定义带成员变量注解MyTag
@Rentention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTag{
//定义两个成员变量,以方法的形式定义
String name();
int age() default 20;
}
//使用
public class Test{
@MyTag(name="test")
public void info(){}
}
5、@Documented注解
Documented注解表明这个注解是由 javadoc记录的,在默认情况下也有类似的记录工具。 如果一个类型声明被注解了文档化,它的注解成为公共API的一部分。
6、@Indexed
@Indexed ,
它可以为Spring的模式注解添加索引,以提升应用启动性能。
使用场景
在应用中有大量使用@ComponentScan扫描的package包含的类越多的时候,Spring模式注解解析耗时就越长。
使用方法
在项目中使用的时候需要导入一个spring-context-indexer jar
包,有Maven和Gradle 两种导入方式,具体可以看官网,我这里使用maven方式,引入jar配置如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<version>5.1.12.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
然后在代码中,对于使用了模式注解的类上加上@Indexed注解即可。如下:
@Indexed
@Controller
public class HelloController {
}
二、注解的作用
编译检查
Annotation 具有"让编译器进行编译检查的作用"。例如,@SuppressWarnings, @Deprecated 和 @Override 都具有编译检查作用。
在反射中使用 Annotation
在reflect库中的的Class, Method, Field 等类都实现了AnnotatedElement接口,这也意味着,我们可以在反射中解析并使用 Annotation,详细是使用方法可以参考第三节中的内容。
根据 Annotation 生成帮助文档
通过给 Annotation 注解加上 @Documented 标签,能使该 Annotation 标签出现在 javadoc 中。
Spring中的注解编程模型
参考文章
三、注解的使用
- 源码级别-APT
在编译期能够获取注解与注解声明的类包括类中所有成员信息,一般用于生成额外的辅助类。 - 字节码级别-字节码增强技术
在编译出Class后,通过修改Class数据以实现修改代码逻辑目的。对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解。 - 运行时-反射
在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定。