欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

对注解的学习

程序员文章站 2022-05-29 13:36:41
...

注解

主要从以下一个点类说注解:

  • 注解是什么,有什么作用
  • 元注解
  • 使用注解将类映射为一张表
  • 基于java config的配置
  • 工作中的注解
    • spring、springmvc中的注解
    • springboot中的注解

注解用来搞什么

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。

注解就是标注某一个类是什么东西,可以理解为标签。

如果在一个类上添加注解,那么可能有以下的作用

  1. 指定这个类是该注解类型的一个类
  2. 可以在运行期动态的获取有关该类或对象的额外信息,
  3. 或者在其他生命期内做一些事,比如在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注解需要注意:

  1. 没有发现它有什么用

@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();
}
  1. @Retention(RetentionPolicy.RUNTIME),表示注解类在VM运行时也会保留,那么就可以通过反射获得注解的信息
  2. @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注解需要注意:

  1. @Retention添加在注释类上时需要有参数RetentionPolicy值
  2. 如果一个注释类没有添加@Retention标注,那么它默认的生命周期时CLASS
  3. 看如下的测试,反正我是没有看懂,为什么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>
 *    &#064;Target(ElementType.ANNOTATION_TYPE)
 *    public &#064;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>
 *    &#064;Target({})
 *    public &#064;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>
 *    &#064;Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
 *    public &#064;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需要注意的是:

  1. 如果注解上不指定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需要注意的是:

  1. 默认情况***解时无法继承的,需要使用@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):用在方法上面表示遇到这个异常就执行以下方法。