java注解的实质,何为注解

注解就是贴标签

(1)注解的作用

1,生成文档。如常用的 @param

2,跟踪代码依赖性,实现替代文件的功能。在 spring 中,主要是减少配置。

3,编译时进行格式检查。如常用的 @override

 

(2)注解的分类

1)按照运行机制划分:
【源码注解→编译时注解→运行时注解】

源码注解:只在源码中存在,编译成.class 文件就不存在了。

编译时注解:在源码和.class 文件中都存在。像前面的 @Override、@Deprecated、@SuppressWarnings,他们都属于编译时注解。

运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解。像 @Autowired 自动注入的这样一种注解就属于运行时注解,它会在程序运行的时候把你的成员变量自动的注入进来。

2)按照来源划分:
【来自 JDK 的注解——来自第三方的注解——自定义注解】

3)元注解:
元注解是给注解进行注解,可以理解为注解的注解就是元注解。

 

(3)java 中常见的注解

1,JDK 的注解

@override 标记该方法为覆盖方法

@Deprecated 标记该方法已经过时

@SuppressWarning() 表示忽略警告

2,java 第三方注解

Spring 的注解

@Autowired 可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作

@Service 用于标注业务层组件

@Controller 用于标注控制层组件(如 struts 中的 action)

@Repository 用于标注数据访问组件,即 DAO 组件

@Component 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

 Mybatis 的注解

@InserProvider 注解为增加

@UpdateProvider 注解为更新

@Options 设置缓存时间

Ps:常用增删改查:@InsertProvider,@DeleteProvider@UpdateProvider 和 @SelectProvider

3,元注解

四个元注解分别是:

@Target

@Retention,

@Documented,

@Inherited

元注解是 java API 提供,是专门用来定义注解的注解,其作用分别如下:

@Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括: 

ElemenetType.CONSTRUCTOR---------------------------- 构造器声明 

ElemenetType.FIELD -------------------------------------- 域声明(包括 enum 实例) 

ElemenetType.LOCAL_VARIABLE------------------------- 局部变量声明 

ElemenetType.METHOD ---------------------------------- 方法声明 

ElemenetType.PACKAGE --------------------------------- 包声明 

ElemenetType.PARAMETER ------------------------------ 参数声明 

ElemenetType.TYPE--------------------------------------- 类,接口(包括注解类型)或 enum 声明 

 

@Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括: 

RetentionPolicy.SOURCE --------------------------------- 注解将被编译器丢弃 

RetentionPolicy.CLASS ----------------------------------- 注解在 class 文件中可用,但会被 VM 丢弃 

RetentionPolicy.RUNTIME VM------- 将在运行期也保留注释,因此可以通过反射机制读取注解的信息。 

 

@Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被 javadoc 工具提取成文档。在 doc 文档中的内容会因为此注解的信息内容不同而不同。相当与 @see,@param 等。

 

@Inherited 允许子类继承父类中的注解。

4,自定义注解

 

 

例子:

定义:

@Target({ElementType.METHOD,ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented public @interface Description {

 String desc();

 String author();

 int age() default 18;

 }

测试:

    @Description(desc="i am Color",author="boy",age=18)

    public String Color() {

        return "red";

    }

因为我们前面定义的作用域是在方法和类接口上,所以这个注解在 Color() 方法上使用是没问题的

 

使用自定义注解:
使用注解的语法:
@< 注解名 >(< 成员名 1>=< 成员值 1>,< 成员名 1>=< 成员值 1>,...)
案例:

    @Description(desc="i am Color",author="boy",age=18)

    public String Color() {

        return "red";

    }

这里的 Description 是我们刚才在自定义注解语法要求里面定义的注解噢,然后我们可以给它的每一个成员变量赋值,注意数据类型。值得注意的是,因为我们前面定义的作用域是在方法和类接口上,所以这个注解在 Color() 方法上使用是没问题的。

解析注解
概念:
通过反射获取类 、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。

 

 

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
1、创建@Table注解
 
package person.lb.annotation;
 
  
 
import java.lang.annotation.ElementType;
 
import java.lang.annotation.Retention;
 
import java.lang.annotation.RetentionPolicy;
 
import java.lang.annotation.Target;
 
  
 
/**
 
 * 表名
 
 * @author nobounds
 
 *
 
 */
 
@Target({ElementType.TYPE})
 
@Retention(RetentionPolicy.RUNTIME)
 
public @interface Table {
 
    String value() default "";
 
}
 
2、创建@Column注解:
 
package person.lb.annotation;
 
  
 
import java.lang.annotation.ElementType;
 
import java.lang.annotation.Retention;
 
import java.lang.annotation.RetentionPolicy;
 
import java.lang.annotation.Target;
 
  
 
/**
 
 * 字段
 
 * @author nobounds
 
 *
 
 */
 
@Target(ElementType.FIELD)
 
@Retention(RetentionPolicy.RUNTIME)
 
public @interface Column {
 
    String name() default "";
 
    String dataType() default "varchar(20)";
 
    String comment() default "";
 
}
 
3、创建实体类Users:
 
package person.lb.annotation;
 
  
 
@Table("users")
 
public class Users {
 
    @Column(name="ID", dataType="int")
 
    private int id;
 
     
 
    @Column(comment="用户名")
 
    private String userName;
 
      
 
    @Column(name="pwd", comment="密码")
 
    private String password;
 
     
 
    @Column(dataType="varchar(25)", comment="邮箱")
 
    private String email;
 
  
 
    public String getUserName() {
 
        return userName;
 
    }
 
  
 
    public void setUserName(String userName) {
 
        this.userName = userName;
 
    }
 
  
 
    public String getPassword() {
 
        return password;
 
    }
 
  
 
    public void setPassword(String password) {
 
        this.password = password;
 
    }
 
  
 
    public String getEmail() {
 
        return email;
 
    }
 
  
 
    public void setEmail(String email) {
 
        this.email = email;
 
    }
 
}
 
4、创建注解处理器AnnotationHandler:
 
package person.lb.annotation;
 
import java.lang.annotation.Annotation;
 
import java.lang.reflect.Field;
 
  
 
public class AnnotationHandler {
 
  
    public static void main(String[] args) {
 
        StringBuilder sql = new StringBuilder("CREATE TABLE ");
 
        try {
 
            Class clazz = Class.forName("person.lb.annotation.Users");
 
            //获取Users类上的Table注解
 
            Table tableAnnotation = (Table) clazz.getAnnotation(Table.class);
 
            //获取表名
 
            String tableName = tableAnnotation.value().toUpperCase();
 
            if("".equals(tableName)) {
 
                tableName = clazz.getName().toUpperCase();
 
            }
 
            sql.append(tableName);
 
            sql.append(" ( \n");
 
            //获取类中的所有字段
 
            Field[] fields = clazz.getDeclaredFields();
 
            for(Field field : fields) {
 
                //获取字段上的所有注解
 
                Annotation[] fieldAnnotations = field.getAnnotations();
 
                if(fieldAnnotations.length > 0) {
 
                    //遍历注解
 
                    for(Annotation fieldAnnotation : fieldAnnotations) {
 
                        //如果是@Field注解,那么进行处理
 
                        if(fieldAnnotation instanceof Column) {
 
                            //获取字段名
 
                            String columnName = ((Column) fieldAnnotation).name().toUpperCase();
 
                            if("".equals(columnName)) {
 
                                columnName = field.getName().toUpperCase();
 
                            }
 
                            //获取数据类型
 
                            String dataType = ((Column) fieldAnnotation).dataType().toUpperCase();
 
                            //获取注释
 
                            String comment = ((Column) fieldAnnotation).comment();
 
                            if("".equals(comment)) {
 
                                sql.append(columnName + "\t" + dataType + ",\n");
 
                            } else {
 
                                sql.append(columnName + "\t" + dataType + " COMMENT '" + comment + "',\n");
 
                            }
 
                        }
 
                    }
 
                }
 
            }
 
            sql.append(" ) ");
 
            System.out.println("生成的sql语句为:\n" + sql.toString());
    
 
        } catch (ClassNotFoundException e) {
 
            e.printStackTrace();
 
        }
 
    }
 
 
}

  

 结果:

1
2
3
4
5
6
7
生成的sql语句为:
CREATE TABLE USERS (
ID    INT,
USERNAME    VARCHAR(20) COMMENT '用户名',
PWD    VARCHAR(20) COMMENT '密码',
EMAIL    VARCHAR(25) COMMENT '邮箱',
 )