注解是什么
注解这一特性出现在JDK1.5及往后的版本中,主要起到减少代码复杂度,减少代码量,降低耦合等作用,在我们日常开发中普遍存在,是java中重要的特性之一,注解在Spring等框架中更是作为重要存在,多数框架中都采取了自定义注解的方式来降低框架的侵入性以及无感知,也是让我们运用框架更加的简单,甚至因此很多人使用应用层过于无感知,无法理解框架的作用,其实都包含在了注解里。
以Spring Boot举例
在Spring框架中,我们在Application中需要添加@SpringBootApplication注解。
以下代码版本为(spring-boot-autoconfigure-2.5.3.jar)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};
@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "nameGenerator"
)
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
首先先理解一点,注解就是一种特殊的接口,是换了一种形式的接口,然后来看在注解类型中进行注解的注解类,我们称之为 meta-annotation(元注解)。
@Target
代表这个注解的作用域,其中value 有以下几种较为常见:
1、ElementType.TYPE 代表这个注解可以在类、接口、注解、枚举类上声明
2、ElementType.METHOD 代表这个注解可以在方法上声明
3、ElementType.FIELD 代表这个注解可以在属性(包括枚举类常量)上声明
还有许多在ElementType类中声明的常量对于不同的作用域,感兴趣可以在JDK(java.lang.annotation)中自行查看
@Retention
代表这个注解的生存周期,其中value 有以下三种:
1、RetentionPolicy.SOURCE 表示这个注解会在这个类被编译成class文件之前就会消除。
2、RetentionPolicy.CLASS 表示这个注解会在生成claas文件时会保留下来,但是不会再VM运行的时候保留。 这也是注解的默认生存周期
3、RetentionPolicy.RUNTIME 表示这个注解会被保留到VM运行时,这也代表这个注解里的值可能会被反射读取。
@documented
没有value值,其作用是在使用javadoc工具生成类的说明文档时保留注解信息。
@Inherited
同样没有值,该注解的作用是在类上使用该注解,其子类也会继承该注解,包括父类注解中里的属性。
@ComponentScan
规定Spring Boot框架扫描报的范围,其value值就是包的路径,需要注意的是,@componentscan虽然包含在@springbootapplication中,但是也可以在Application中覆盖@springbootapplicaiton中的默认扫描范围。
@EnableAutoConfiguration
该注解的效果是启动自动配置类,接下来主要讲解其中的核心逻辑,可以看到该注解最重要的就是
@Import({AutoConfigurationImportSelector.class})
这个注解的作用是导入了AutoConfigurationImportSelector.class类,在这个类中,重要的是
SpringFactoriesLoader.loadFactoryNames()
对于@EnableAutoConfiguration注解来说SpringFactoriesLoader类其主要作用就是从META-INF/spring-factories配置文件下加载自动配置类到容器中。其本身的作用是对于spring框架的一种拓展方案,类似于java中的SPI机制SpringBootConfiguration。
@SpringBootConfiguration
其作用与@configuration 作用类似,声明是配置文件,区别在于 @SpringBootConfiguration是springboot框架中的配置声明,@configuration是spring下的配置声明