java mysql 反射_java基础之反射和注解3

第三节 注解的使用

3.1认识注解

Annotation ,JDK1.5新提供的技术

我们在编程中经常会使用到注解,作用有:

1)编译检查:比如@SuppressWarnings, @Deprecated 和 @Override 都具有编译检查作用

2)替代配置文件:使用反射来读取注解信息

目前大部分框架(如Spring)都使用了注解简化代码并提高编码的效率(使用注解之前使用的xml进行配置)

注解其实就是代码里的特殊标记,它用于替代配置文件:传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行。在Java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。 注解可以标记在包、类、属性、方法,方法参数以及局部变量上,且同一个地方可以同时标记多个注解。注解可以在编译(source),类加载(class),运行时(runtime)被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署

3.2内置注解

主要有三个内置注解

1.@Override - 检查该方法是否是重载方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

2.@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。

3.@SuppressWarnings - 指示编译器去忽略注解中声明的警告。

从 Java 7 开始,额外添加了 3 个注解:

@SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

Java 8 开始支持,额外添加了两个注解

@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。

@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

3.3元注解

元注解是指注解的注解,在JDK 1.5中提供了4个标准的用来对注解类型进行注解的注解类。可以使用这4个元注解来对我们自定义的注解类型进行注解

1. @Retention用来约束注解的生命周期,分别有三个值,源码级别(source),类文件级别(class)或者运行时级别(runtime),若没有 @Retention,则默认是 RetentionPolicy.CLASS。其含有如下:

SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)

CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机中)。

RUNTIME:注解信息将在运行期(JVM)也保留,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息),如SpringMvc中的@Controller、@Autowired、@RequestMapping等。

2. @Target -用来约束注解可以应用的地方(如方法、类或字段),其中ElementType是枚举类型。若没有 @Target,则该 Annotation 可以用于任何地方。

3. @Documented - 标记这些注解是否包含在用户文档中。

4. @Inherited - 指示注解类型被自动继承。如果在注解类型声明中存在 Inherited 元注解,并且用户在某一类声明中查询该注解类型,同时该类声明中没有此类型的注解,则将在该类的超类中自动查询该注解类型。

3.4自定义注解

【示例11】自定义注解

package com.bjsxt.demo1;

import java.lang.annotation.*;

import java.util.Date;

import java.util.List;

/** 元注解:用于注解注解的注解* 用于帮助我们定义注解而使用的注解* @Target 控制我们自己定义的注解可以使用的位置* 如果不加该注解 意味着该注解可以使用在任意位置* @Retention 控制我们自己定义的注解的声明周期* 我们的注解在程序运行的那个阶段有效* SOURCE 源代码中 一般用于编写代码的提示* CLASS 编译后代码的处理* RUNTIME运行时可以使用** */

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

@Retention(RetentionPolicy.RUNTIME)

public @interface Anno {

/** 注解的属性* 1注解的属性 不可以使用访问修饰符修饰默认必须是public* 2属性的语法* 单个属性语法 数据类型 属性名();* 数组属性语法 数据类型[] 属性名();* 枚举作为属性 枚举类型 属性名();* 枚举数组作为属性 枚举类型[] 属性名();* 3属性的赋值* @Anno(i=10,arr={10,20},week=Week.星期五,weeks={Week.星期一,Week.星期二})* 4属性的默认值* 数据类型 属性名() default 值;* 5赋值时可以缺省的属性名* 当注解中只有一个属性 推荐使用 value作为属性名* 当属性名是value且仅有一个属性时,属性名可以省略不写* */

String value() default "";

int i() default 1;

int[] arr() default {};

Week week() default Week.星期日;

Week[] weeks() default {Week.星期五,Week.星期四};

}

总结:

定义注解的关键字是@interface

自定义注解中可以定义多个配置参数,不是成员方法,不是成员变量;说明参数的名称,以及参数值的类型

如果只有一个配置参数,一般命名为value

如果配置参数是value,并且只有一个配置参数,value可以省略

注解一定要配套的使用读取注解的程序,否则注解是没有什么意义

注意:

定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation。

和我们通常的 implements实现接口的方法不同。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注解后,该注解不能继承其他注解或接口。

注解常见的API及其关系如下

3.5 反射结合注解完成ORM映射

数据库中的表格和JAVA中的实体类就是一种映射关系,好比,人和影子,地图和实际地理,用何种方式能够表达出二者的映射呢? 就是sql语句

目前大部分框架(如Spring、MyBatis、SpringMVC)都使用了注解简化代码并提高编码的效率(使用注解之前使用的xml进行配置)。

【示例12】反射结合注解完成ORM映射

准备两个注解

/** 体现类名和表格名称之间的映射关系* */

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface TableAnno {

String value();

}

/** 体现实体类属性和数据库表格字段的映射关系* */

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface FieldAnno {

// 名称的对应关系 String fieldName();

// 数据类型的对应关系 String fieldType();

// 数据大小的对应关系 int length();

// 约束的对应关系 String constraint();

}

在实体类上添加注解

@SuppressWarnings("all")

@TableAnno("person")

public class Person {

@FieldAnno(fieldName ="pid",fieldType ="int",length = 6,constraint = "primary key auto_increment")

private int pid;

@FieldAnno(fieldName ="pname",fieldType ="varchar",length =5,constraint = "not null")

private String pname;

@FieldAnno(fieldName ="page",fieldType ="int",length =2,constraint = "check (page >0 and page <80)")

private int page;

}

使用反射技术编写注解读取和处理程序

public class ORMUtil {

/*** 根据类的全路径名,生成对应数据库表格的sql语句的方法* @param classname* @return*/

public static String getORMSql(String classname) throws Exception{// com.bjsxt.demo2.Person StringBuilder sbd =new StringBuilder("create table ");

//获得类的字节码 Class clazz=Class.forName(classname);// personClass TableAnno tableAnno =(TableAnno) clazz.getAnnotation(TableAnno.class);

String value = tableAnno.value();

sbd.append(value);

sbd.append(" (");

/*获取属性上的注解*/

Field[] fs = clazz.getDeclaredFields();

for (int i =0;i

Field f =fs[i];

FieldAnno fanno = f.getAnnotation(FieldAnno.class);

String fieldName = fanno.fieldName();

sbd.append(fieldName+" ");

String fieldType = fanno.fieldType();

int length = fanno.length();

sbd.append(fieldType+"("+length+") ");

String constraint = fanno.constraint();

sbd.append(constraint);

if(i

sbd.append(",");

}

}

sbd.append(")");

return sbd.toString();

}

}

测试代码

public static void main(String[] args) throws Exception {

String ormSql = ORMUtil.getORMSql("com.bjsxt.demo2.Person");

System.out.println(ormSql);

}

总结:注解一定要有配套的注解读取和处理程序,否则是没有意义的.注解就是信息的一种标志,不是功能直接实现

本节作业:

1.使用java中的内置注解

2.完成一个自定义注解

3.完成emp和数据库之间的ORM映射处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值