注解(代码标记)
概念
可以通过反射机制获取代码标记中的元数据。
在编译器生成类文件时,标记可以被嵌入到字节码中。Java 虚拟机可以保留标记内容,在运行时可以获取到标记内容
元注解(Java提供的)
由Java提供的元注解,所谓元注解就是标记其他注解的注解
@Target(约束自定义注解)
用来约束注解可以应用的地方(如方法、类或字段),其中ElementType是枚举类型,也代表可能的取值范围
public enum ElementType {
/**标明该注解可以用于类、接口(包括注解类型)或enum声明*/
TYPE,
/** 标明该注解可以用于字段(域)声明,包括enum实例 */
FIELD,
/** 标明该注解可以用于方法声明 */
METHOD,
/** 标明该注解可以用于参数声明 */
PARAMETER,
/** 标明注解可以用于构造函数声明 */
CONSTRUCTOR,
/** 标明注解可以用于局部变量声明 */
LOCAL_VARIABLE,
/** 标明注解可以用于注解声明(应用于另一个注解上)*/
ANNOTATION_TYPE,
/** 标明注解可以用于包声明 */
PACKAGE,
/**
* 标明注解可以用于类型参数声明(1.8新加入)
* @since 1.8
*/
TYPE_PARAMETER,
/**
* 类型使用声明 类型检查(1.8新加入)
* @since 1.8
*/
TYPE_USE
/**
* 标注在类型参数上(1.8后加入)
**/
TYPE_PARAMETER
}
当注解未指定Target值时,则此注解可以用于任何元素之上,多个值使用{}包含并用逗号隔开
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
@Retention(约束注解的生命周期)
分别有三个值,源码级别(source),类文件级别(class)或者运行时级别(runtime),其含有如下:
SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
CLASS:注解在class文件中可用,但会被JVM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机中),请注意,当注解未定义Retention值时,默认值是CLASS,如Java内置注解,@Override、@Deprecated、@SuppressWarnning等
RUNTIME:注解信息将在运行期(JVM)也保留,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息),如SpringMvc中的@Controller、@Autowired、@RequestMapping等
@Override(声明覆盖了父类方法)
用于标明此方法覆盖了父类的方法
@Deprecated(标明已经过时的方法或类)
@SuppressWarnnings(关闭编译器警告)
用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告
@Documented(被修饰的注解会生成到javadoc中)
使用javadoc命令生成文档
@Inherited(让子类继承父类的注解)
@Repeatable(可以在同个位置上标注重复注解)
元注解@Repeatable是JDK1.8新加入的,它表示在同一个位置重复相同的注解。在没有该注解前,一般是无法在同一个类型上使用相同的注解的
自定义注解
创建SQL建表语句
1、创建默认属性注解
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Constraints {
//是否为主键
boolean primaryKey() default false;
//是否为空
boolean allowNull() default false;
//是否唯一
boolean unique() default false;
}
//默认表名
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
String name() default "";
}
//Int类型列名
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
String name() default "";
Constraints constraints() default @Constraints;
}
//String类型列名
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
String name() default "";
int value() default 0;
Constraints constraints() default @Constraints;
}
2、通过反射调用注解,获得其默认值
public class createTable {
public static String createTableSql(String className) throws ClassNotFoundException {
//通过反射获取该类
Class> cl = Class.forName(className);
//获取该类的@DBTable注解
DBTable dbTable = cl.getAnnotation(DBTable.class);
if(dbTable ==null){
System.out.println("当前"+className+"不存在");
return null;
}
String tableName = dbTable.name().toUpperCase();
List columnList = new ArrayList();
for(Field field : cl.getDeclaredFields()){
String columnName = null;
Annotation[] annotations = field.getDeclaredAnnotations();
if(annotations[0] instanceof SQLInteger){
SQLInteger sqlInteger = (SQLInteger) annotations[0];
if(sqlInteger.name().length()<1){
columnName = field.getName();
}else {
columnName = sqlInteger.name();
}
columnList.add(columnName+" INT "+getConstraints(sqlInteger.constraints()));
}
if(annotations[0] instanceof SQLString){
SQLString sqlString = (SQLString) annotations[0];
if(sqlString.name().length()<1){
columnName = field.getName();
}else{
columnName = sqlString.name();
}
columnList.add(columnName+" VARCHAR("+sqlString.value()+") "+getConstraints(sqlString.constraints()));
}
}
StringBuilder stringBuilder = new StringBuilder(
"CREATE TABLE " +tableName +"("
);
for(String column : columnList){
stringBuilder.append("\n"+column+",");
}
String createSQL = stringBuilder.substring(0,stringBuilder.length()-1)+");";
return createSQL;
}
public static String getConstraints(Constraints constraints){
String con = "";
if(!constraints.allowNull()){
con += " NOT NULL ";
}
if(constraints.primaryKey()){
con +=" PRIMARY KEY ";
}
if(constraints.unique()){
con +=" UNIQUE ";
}
return con;
}
}
3、调用运行时的类,获得建表语句
public class Application {
public static void main(String[] args) throws ClassNotFoundException {
String[] arg={"annotation.User"};
for(String className : arg){
System.out.println(createTable.createTableSql(className));
}
}
}
![image-20210113161358760.png](https://upload-images.jianshu.io/upload_images/6068127-64940a98b6e431e3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)