对注解的学习
注解
主要从以下一个点类说注解:
- 注解是什么,有什么作用
- 元注解
- 使用注解将类映射为一张表
- 基于java config的配置
- 工作中的注解
- spring、springmvc中的注解
- springboot中的注解
注解用来搞什么
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。
注解就是标注某一个类是什么东西,可以理解为标签。
如果在一个类上添加注解,那么可能有以下的作用
- 指定这个类是该注解类型的一个类
- 可以在运行期动态的获取有关该类或对象的额外信息,
- 或者在其他生命期内做一些事,比如在IDE编辑器中显示删除线等
注解长什么样
一般看到的注解的样式有以下几种:
- 内容为空
- 内容中有名为value()的空函数,就好比在类中定义了一个value的变量
- 内容中有其他空函数,比如id(),age() 好比是定义了id与age两个变量
内容为空比如@Documented,使用时不加括号,直接使用比如:@Documented
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
内容中包含value()的空函数,比如@Retention
- 当没有指定default时,使用@Retention**必须指定值,如@Retention(RetentionPolicy.RUNTIME)**
- 如果使用default指定默认值,那么就可以省略内容,比如@Retention()
- value这种属于特殊情况,正常使用应该时应使用@Retention(value=RetentionPolicy.RUNTIME),但是value特殊,可以省略不写
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
内容中有其他空函数:使用时需要指定值,比如:@TestAnnotation(id=“zt”,age=27)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
String id();
int age();
}
元注解
元注解是用于定义一个注解是什么东西,比如使用元注解@Retention(RetentionPolicy.RUNTIME)标注一个注解类,那么这个注解类注解在类A会一直存在到运行时。运行时就可以获得某个类的注解信息进行一些邪恶的操作。这就类似于使用XML配置,指定了某个类的属性值,运行时动态的获取这个值进行一些操作。
元注解,可以”对注解进行注解“的注解。元注解可以修饰其他元注解,甚至可以修饰自己在我的jdk8中,有如下几个元注解:
- Documented
- Retention
- Target
- Inherited
- Native
- Repeatable
@Documented
元注解,添加在注解类上,使用该注解标注的注解类会包含在javadoc文档中,但是我生成javadoc时,即使注解上不包含@Documented也会生成,比较困惑
/**
* Indicates that annotations with a type are to be documented by javadoc
* and similar tools by default. This type should be used to annotate the
* declarations of types whose annotations affect the use of annotated
* elements by their clients. If a type declaration is annotated with
* Documented, its annotations become part of the public API
* of the annotated elements.
*
* @author Joshua Bloch
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
上面是@Documented的源码,主要包含:
- @Documented,表示下面的Documented注解类包含在javadoc文档中
- @Retention标明下面的Documented注解类的生命周期,此时表示使用@Documented标注的类可以在运行时获得
- @Target为ElementType.ANNOTATION_TYPE,表示下面的Documented注解类可以用于只能用于标注注解类。
生成javadoc使用的命令如下:
//javadoc命令用于生成java文档
//-d指定生成的文档的位置,-sourcepath指定搜索类文件的基准目录
//annotation是我要生成文档的类所属的包名
javadoc -d dochome -sourcepath . annotation
最后生成的文档如下:
对于javadoc文档格式的详细介绍见 https://www.cnblogs.com/KingIceMou/p/7169744.html
使用@Documented注解需要注意:
- 没有发现它有什么用
@Rentention
元注解,用于标注注解,使用它标注的注解的生命周期由参数决定
/**
* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* <p>A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.2 @Retention
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
- @Retention(RetentionPolicy.RUNTIME),表示注解类在VM运行时也会保留,那么就可以通过反射获得注解的信息
- @Target(ElementType.ANNOTATION_TYPE),表示被修饰的注解类只能修饰注解
RetentionPolicy类如下:
/**
* Annotation retention policy. The constants of this enumerated type
* describe the various policies for retaining annotations. They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author Joshua Bloch
* @since 1.5
*/
public enum RetentionPolicy {
/**
* 注解会被编译器丢弃
*/
SOURCE,
/**
* 注解在class文件中可用,但是会被VM丢弃
*/
CLASS,
/**
* VM在运行期也会保留注解,因此可以通过反射机制读取注解的信息
*/
RUNTIME
}
使用@Retention注解需要注意:
- @Retention添加在注释类上时需要有参数RetentionPolicy值
- 如果一个注释类没有添加@Retention标注,那么它默认的生命周期时CLASS
- 看如下的测试,反正我是没有看懂,为什么MyRetention2.class与MyRetention3.class反编译后为空
测试:下面创建一个注解三个注解MyRetention,注解分别运行在RetentionPolicy为SOURCE/CLASS/RUNTIME。将注解标注一个类TestRetention,该类输出注解个数,并反编译其class类。
MyRetention.java
package annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.SOURCE)
public @interface MyRetention {
}
MyRetention2.java
package annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface MyRetention2 {
}
MyRetention3.java
package annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRetention3 {
}
TestRetention.java
package annotation;
@MyRetention
@MyRetention2
@MyRetention3
public class TestRetention {
public static void main(String[] args) {
TestRetention retention2 = new TestRetention();
System.out.println(retention2.getClass().getDeclaredAnnotations().length);//1
}
}
@Target
元注解,用于表示被标注的注解可以标注的是类/方法/构造器…..
package java.lang.annotation;
/**
* Indicates the contexts in which an annotation type is applicable. The
* declaration contexts and type contexts in which an annotation type may be
* applicable are specified in JLS 9.6.4.1, and denoted in source code by enum
* constants of {@link ElementType java.lang.annotation.ElementType}.
*
* <p>If an {@code @Target} meta-annotation is not present on an annotation type
* {@code T} , then an annotation of type {@code T} may be written as a
* modifier for any declaration except a type parameter declaration.
*
* <p>If an {@code @Target} meta-annotation is present, the compiler will enforce
* the usage restrictions indicated by {@code ElementType}
* enum constants, in line with JLS 9.7.4.
*
* <p>For example, this {@code @Target} meta-annotation indicates that the
* declared type is itself a meta-annotation type. It can only be used on
* annotation type declarations:
* <pre>
* @Target(ElementType.ANNOTATION_TYPE)
* public @interface MetaAnnotationType {
* ...
* }
* </pre>
*
* <p>This {@code @Target} meta-annotation indicates that the declared type is
* intended solely for use as a member type in complex annotation type
* declarations. It cannot be used to annotate anything directly:
* <pre>
* @Target({})
* public @interface MemberType {
* ...
* }
* </pre>
*
* <p>It is a compile-time error for a single {@code ElementType} constant to
* appear more than once in an {@code @Target} annotation. For example, the
* following {@code @Target} meta-annotation is illegal:
* <pre>
* @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
* public @interface Bogus {
* ...
* }
* </pre>
*
* @since 1.5
* @jls 9.6.4.1 @Target
* @jls 9.7.4 Where Annotations May Appear
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
其中的ElementType如下:
package java.lang.annotation;
/**
* The constants of this enumerated type provide a simple classification of the
* syntactic locations where annotations may appear in a Java program. These
* constants are used in {@link Target java.lang.annotation.Target}
* meta-annotations to specify where it is legal to write annotations of a
* given type.
*
* <p>The syntactic locations where annotations may appear are split into
* <em>declaration contexts</em> , where annotations apply to declarations, and
* <em>type contexts</em> , where annotations apply to types used in
* declarations and expressions.
*
* <p>The constants {@link #ANNOTATION_TYPE} , {@link #CONSTRUCTOR} , {@link
* #FIELD} , {@link #LOCAL_VARIABLE} , {@link #METHOD} , {@link #PACKAGE} ,
* {@link #PARAMETER} , {@link #TYPE} , and {@link #TYPE_PARAMETER} correspond
* to the declaration contexts in JLS 9.6.4.1.
*
* <p>For example, an annotation whose type is meta-annotated with
* {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
* field declaration.
*
* <p>The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS
* 4.11, as well as to two declaration contexts: type declarations (including
* annotation type declarations) and type parameter declarations.
*
* <p>For example, an annotation whose type is meta-annotated with
* {@code @Target(ElementType.TYPE_USE)} may be written on the type of a field
* (or within the type of the field, if it is a nested, parameterized, or array
* type), and may also appear as a modifier for, say, a class declaration.
*
* <p>The {@code TYPE_USE} constant includes type declarations and type
* parameter declarations as a convenience for designers of type checkers which
* give semantics to annotation types. For example, if the annotation type
* {@code NonNull} is meta-annotated with
* {@code @Target(ElementType.TYPE_USE)}, then {@code @NonNull}
* {@code class C {...}} could be treated by a type checker as indicating that
* all variables of class {@code C} are non-null, while still allowing
* variables of other classes to be non-null or not non-null based on whether
* {@code @NonNull} appears at the variable's declaration.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.4.1 @Target
* @jls 4.1 The Kinds of Types and Values
*/
public enum ElementType {
//类,接口,注解,枚举类申明
TYPE,
//域声明
FIELD,
//方法声明
METHOD,
//参数声明
PARAMETER,
//构造器声明
CONSTRUCTOR,
//局部变量声明
LOCAL_VARIABLE,
//注解声明
ANNOTATION_TYPE,
//包
PACKAGE,
//1.8后添加的,用于标注类型,使用在类型的声明之前,注意此处是声明,具体使用需要是 TYPE_USE
// public class TestTarget<@MyTarget1 T>
// public class TestTarget<@MyTarget1 String>
TYPE_PARAMETER,
//1.8添加,标注在类型使用之前,其中类型声明也可以使用
//public class TestTarget<@MyTarget1 T> {
//@MyTarget1 TestTarget<@MyTarget1 String> target = new @MyTarget1 TestTarget<@MyTarget1 String>();
//@MyTarget1 String string = new @MyTarget1 String();
//string = (@MyTarget1 String) new @MyTarget1 Object();
TYPE_USE
}
使用@Target需要注意的是:
- 如果注解上不指定Target,那么默认可以用在所有的ElementType上
@Inherited
元注解,用于用于继承。具体使用方式为:创建自定义的注解类@MyInherited,使用注解标注类Father,当Son类继承Father类时,Son也继承了Father上的标注@MyInherited
/**
* Indicates that an annotation type is automatically inherited. If
* an Inherited meta-annotation is present on an annotation type
* declaration, and the user queries the annotation type on a class
* declaration, and the class declaration has no annotation for this type,
* then the class's superclass will automatically be queried for the
* annotation type. This process will be repeated until an annotation for this
* type is found, or the top of the class hierarchy (Object)
* is reached. If no superclass has an annotation for this type, then
* the query will indicate that the class in question has no such annotation.
*
* <p>Note that this meta-annotation type has no effect if the annotated
* type is used to annotate anything other than a class. Note also
* that this meta-annotation only causes annotations to be inherited
* from superclasses; annotations on implemented interfaces have no
* effect.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.3 @Inherited
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
示例代码:
MyInherited.java
package annotation.inherited;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface MyInherited {
public String name() default "zt";
}
Father.java
package annotation.inherited;
@MyInherited(name="网速20M")
public class Father {
}
Son.java
package annotation.inherited;
import java.lang.annotation.Annotation;
public class Son extends Father{
public static void main(String[] args) {
Son son = new Son();
Annotation[] annotations = son.getClass().getAnnotations();
for(Annotation annotation: annotations) {
System.out.println(annotation.toString());
//@annotation.inherited.MyInherited(name=网速20M)
}
}
}
使用@Inherited需要注意的是:
- 默认情况***解时无法继承的,需要使用@Inherited
@Native
元注解,声明周期为SOURCE,标注在域上,表示常量可能被本地代码引用,具体使用没有见到
package java.lang.annotation;
/**
* Indicates that a field defining a constant value may be referenced
* from native code.
* 表示常量有可能被本地代码引用
* The annotation may be used as a hint by tools that generate native
* header files to determine whether a header file is required, and
* if so, what declarations it should contain.
*
* @since 1.8
*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Native {
}
@Repeatable
元注解,使用它修饰的注解,可以多次添加到同一个东西上。
package java.lang.annotation;
/**
* The annotation type {@code java.lang.annotation.Repeatable} is
* used to indicate that the annotation type whose declaration it
* (meta-)annotates is <em>repeatable</em>. The value of
* {@code @Repeatable} indicates the <em>containing annotation
* type</em> for the repeatable annotation type.
*
* @since 1.8
* @jls 9.6 Annotation Types
* @jls 9.7 Annotations
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
/**
* Indicates the <em>containing annotation type</em> for the
* repeatable annotation type.
* @return the containing annotation type
*/
Class<? extends Annotation> value();
}
假如现存一个注解@Role,某个用户有多个角色属于多个Role,那么此时可以有几种写法:
第一种:第一种方法与第二种方法本质上是相同的,都是使用一个数组作为value存储角色对象,只不过第一种使用字符串表示角色,第二种使用Role对象表示角色
Role.java
package annotation.repeatable.t1;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
String[] value();
}
User1.java
package annotation.repeatable.t1;
import java.lang.annotation.Annotation;
@Role({"发文角色", "收文角色"})
public class User1 {
public static void main(String[] args) {
Annotation[] annotations =
User1.class.getAnnotations();
for(Annotation annotation: annotations) {
System.out.println(annotation);
}
}
}
第二种写法:
Role.java
package annotation.repeatable.t2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
String value() default "null";
}
Roles.java
package annotation.repeatable.t2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Roles {
Role[] value();
}
User2.java
package annotation.repeatable.t2;
import java.lang.annotation.Annotation;
@Roles({@Role("发文管理"), @Role("收文管理"), @Role()})
public class User2 {
public static void main(String[] args) {
Annotation[] annotations =
User2.class.getAnnotations();
for(Annotation annotation: annotations) {
Roles roles = (Roles)annotation;
for(Role role: roles.value()) {
System.out.println(role.value());
}
}
}
}
第三种:使用@Repeatable的方式
Role.java
package annotation.repeatable.t3;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Repeatable(Roles.class)
public @interface Role {
String role();
}
Roles.java
package annotation.repeatable.t3;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Roles {
Role[] value();
}
User3.java
package annotation.repeatable.t3;
import java.lang.annotation.Annotation;
@Role(role="发文管理")
@Role(role="收文管理")
@Role(role="null")
public class User3 {
public static void main(String[] args) {
Annotation[] annotations =
User3.class.getAnnotations();
for(Annotation annotation: annotations) {
Roles roles = (Roles) annotation;
System.out.println(roles.value()[0]);
System.out.println(roles.value()[1]);
System.out.println(roles.value()[2]);
}
}
}
关于一张数据库表
当前存在一个java类,计划使用该java类来映射到数据库中的一张表,那么映射首先是去数据库中建立一张表,为了满足这个需求,先定义一些有关数据库的注解,将这些注解添加到java类上。然后使用工具类生成建表语句。
将表使用注解表示
DATale.java表注解
package annotation.table;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
String tableName() default "";
}
Constrains.java表约束注解:
package annotation.table;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
String unique() default "";
String notNull() default "not null";
String primaryKey() default "";
}
SQLVarchar.java 定义表列类型的注解
package annotation.table;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLVarchar {
int length() default 2048;
Constraints constraints();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface SQLInt {
Constraints constraints();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface SQLDATE {
String date() default "2017-01-01";
Constraints constraints();
}
UserTable.java实体类
package annotation.table;
import java.sql.Date;
@DBTable(tableName="User")
public class UserTable {
//用户名
@SQLVarchar(length=200,
constraints=@Constraints(notNull="not null", primaryKey="primary key", unique = "unique"))
String userName;
//用户年龄
@SQLInt(constraints=@Constraints(notNull="not null"))
int age;
//用户出生日期
@SQLDATE(constraints=@Constraints())
Date birthDate;
}
SQLUtil.java 生成sql语句的工具类:
package annotation.table;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class SQLUtil {
public static String generateCreateSQL(Class<?> cls) {
Annotation annotation = null;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("create table ");
//获得表名
annotation = cls.getAnnotations()[0];
String tableName = ((DBTable) annotation).tableName();
stringBuilder.append(tableName + "( ");
//获得各个列名以及约束
Field[] fields = cls.getDeclaredFields();
for(Field field: fields) {
stringBuilder.append(field.getName() + " ");
Annotation[] fieldAnnotations = field.getDeclaredAnnotations();
for(Annotation annotation2: fieldAnnotations) {
if (annotation2 instanceof SQLVarchar) {
//获得长度
SQLVarchar sqlVarchar = (SQLVarchar) annotation2;
stringBuilder.append("varchar(" + sqlVarchar.length() + ") ");
//获得约束
stringBuilder.append(sqlVarchar.constraints().primaryKey() + " ");
stringBuilder.append(sqlVarchar.constraints().notNull() + " ");
stringBuilder.append(sqlVarchar.constraints().unique() + " ,");
}else if(annotation2 instanceof SQLInt) {
SQLInt sqlInt = (SQLInt) annotation2;
stringBuilder.append("int ");
//获得约束
stringBuilder.append(sqlInt.constraints().primaryKey() + " ");
stringBuilder.append(sqlInt.constraints().notNull() + " ");
stringBuilder.append(sqlInt.constraints().unique() + " ,");
}else if(annotation2 instanceof SQLDATE) {
SQLDATE sqlDATE = (SQLDATE) annotation2;
stringBuilder.append("date ");
stringBuilder.append("default '" + sqlDATE.date() + "'");
//获得约束
stringBuilder.append(sqlDATE.constraints().primaryKey() + " ");
stringBuilder.append(sqlDATE.constraints().notNull() + " ");
stringBuilder.append(sqlDATE.constraints().unique() + " ,");
}else {
}
}
}
stringBuilder.deleteCharAt(stringBuilder.length()-1).append(" );");
return stringBuilder.toString();
}
public static void main(String[] args) {
String string = SQLUtil.generateCreateSQL(UserTable.class);
System.out.println(string);
}
}
Spring的JavaConfig
不使用xml来表示bean之间的关系,而是使用注解。JavaConfig就是使用注释来描述Bean配置的组件。
常见的JavaConfig的注解有:
- @Import:将多个javaconfig格式的配置文件合并到一起,并将合并后的文件作为配置文件
- @ImportResource(“classpath:/aop-config.xml”):导入xml格式的配置文件
- @Configuration:将被注解的类作为Spring的核心配置文件
- @Bean:将被注解的方法的返回值作为被spring管理的实例
- @PropertySource(“classpath:/jdbc.properties”) :指定数据库配置文件
- @Value(“${spring.datasource.username}”) :指定配置文件中的值
代码示例:
package com.yiibai.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
//当前类作为一个配置文件存在,其中这个配置文件引入两个配置文件:CustomerConfig与SchedulerConfig
@Configuration
@Import({ CustomerConfig.class, SchedulerConfig.class })
public class AppConfig {
//定义一个bean,名称为helloworld,实现为HelloworldImpl()
@Bean(name="helloworld")
public Helloeorld getHello(){
return new HelloworldImpl();
}
}
工作中注解
Spring、SpringMVC中的常见注解解析
@Component、@Controller、@Service、@Repository:默认扫描的bean
@Cacheable、@CacheEvict、@CachePut、@CacheFlush:将方法的参数与方法的返回结果缓存起来
@AutoWired、@Resource(属于javax)、@Qualifier、@Required:装配对象
@PostConstruct、@PreDestroy:PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy方法在destroy()方法执行执行之后执行
@Scope:在 Spring IoC 容器是指其创建的 Bean 对象相对于其他 Bean 对象的请求可见范围。在 Spring IoC 容器中具有以下几种作用域:基本作用域(singleton、prototype),Web 作用域(reqeust、session、globalsession),自定义作用域。
@InitBinder :被标注的方法,可以对WebDataBinder对象进行初始化。WebDataBinder是DataBinder的子类,用于完成由表单到JavaBean属性的绑定。 比如可以自定义对日期,boolean的处理等
@Import、@ImportResource:合并多个spring的配置文件、引入xml配置文件、引入Bean
@Async:异步调用,相当于将被注解的方法至于Future中执行
@ModelAttribute:注解作用在方法上或者方法的参数上,表示将被注解的方法的返回值或者是被注解的参数作为Model的属性加入到Model中,然后Spring框架自会将这个Model传递给ViewResolver。
@SessionAttributes:将Model中的数据存储在session中
@RequestParam、@PathVariable :用于从request中接收请求的,两个都可以接收参数,关键点不同的是前者 是从request里面拿取值,而后者是从一个URI模板里面来填充
@RequestBody:post请求的时候才会使用这个请求,把参数丢在requestbody里面
@ResponseBody:将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML。需要注意的呢,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
@RequestHeader、@CookieValue:用于映射请求头数据到Controller方法的对应参数。
@RequestMapping:用来处理请求地址映射的注解
SpringBoot中的常见注解
@SpringBootApplication:被 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解所修饰,简化配置
@Configuration:将被注解的类作为一个Bean配置,交于容器进行管理
@EnableAutoConfiguration:启用 Spring 应用程序上下文的自动配置,试图猜测和配置您可能需要的bean。自动配置类通常采用基于你的 classpath 和已经定义的 beans 对象进行应用。
@ComponentScan:注解会自动扫描指定包下的全部标有 @Component注解 的类,并注册成bean
@RestController:相当于在类上添加了@Controller,且在被注解的类中天记录@RequestMapping的方法上添加了@ResponseBody
@JsonBackReference、@JsonManagedReference、@JsonIgnore:为了解决对象中存在双向引用导致的无限递归(infinite recursion)
@ControllerAdvice:包含@Component,可以被扫描到。统一处理异常。
@ExceptionHandler(Exception.class):用在方法上面表示遇到这个异常就执行以下方法。