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、创建@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(); } } }
结果:
生成的sql语句为: CREATE TABLE USERS ( ID INT, USERNAME VARCHAR(20) COMMENT '用户名', PWD VARCHAR(20) COMMENT '密码', EMAIL VARCHAR(25) COMMENT '邮箱', )