注解JDK5.0
- 以@开始的标记,就是注解, 在编译,类加载,运行时被读取,并执行相应处理
- 框架中我们用注解,通过反射读取注解,然后处理,做一些相应的事情,反射做的
- 实例:就像标签一样,找到该注解,(注解中有value),直接找个某个类,就不用配置过多的依赖项
- JDK提供了三个默认的注解
自定义注解
- 参照@SuppressWarnings来定义
- 注解声明为@interface
- 内部定义成员,通常使用value表示
- 可以指定成员的默认值,使用default,value中可以再改
//自定义的注解,带有value的,default可以有可以没有
public @interface MyAnnotation{
String value() default = "Hello";
}
使用注解时,需要指定value,有默认值就算了
@MyAnnotation(value="xxx");
-
那标识了注解能干啥?实际上这要配合反射来使用,通过反射来获取注解,读取value来判断它是干什么的
-
比如说LoginServlet,它的注解是@WebServlet("/login"),那么通过反射读取WebServlet注解,再获取注解的value,这个注解在LoginServlet类上,所以通过反射生成LoginServlet类对象
- 这样的过程和xml配置的过程是一样的,先找Name,在注入依赖项
-
元注解:注解的注解
- Retention:指定修的注解的生命周期,SOURCE/CLASS(默认行为)/RUNTIME是有声明为RUNTIME生命周期的注解才能通过反射来获取
- Target:用于指定修饰的注解能用于修饰哪些程序的元素
- Retention,Target两个注解一般在自定义注解时,必须指明,不然没有意义
通过反射获取注解的信息
Class clazz = Person.class;
//获取类的注解
Annotation[] annotations = clazz.getAnnotations();
for(Annotation annos : anntotation){
System.out.println(annos);//获取到注解的value
}
注解和反射在框架中的实例
- 先自定义一个注解 Check
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
- 写一个需要测试类Calculator
public class Calculator {
/**
* 注解就像标签一样,被通过反射找到添加了Check注解的方法
*/
@Check
public void add(){
System.out.println("1 + 0 = " + (1+0));
}
@Check
public void sub(){
System.out.println("1 + 0 = " + (1-0));
}
@Check
public void mul(){
System.out.println("1 + 0 = " + (1*0));
}
@Check
public void div(){
System.out.println("1 + 0 = " + (1/0));
}
public void show(){
System.out.println("没有添加注解的方法不会被检测到");
}
}
- 写测试类Test
public class TestAnnotations {
public static void main(String[] args) {
BufferedWriter bw = null;
try {
//1. 创建要测试类对象
Calculator c = new Calculator();
//2. 创建Calss对象,获取 CLASS对象
Class clazz = c.getClass();
//3. 通过反射动态获取方法
Method[] methods = clazz.getMethods();
bw = new BufferedWriter(new FileWriter("bug.txt"));
int count = 0;//bug出现的次数
//循环遍历method数组中存放的方法
for (Method method : methods) {
//判断每个方法是否上面有Check注解
if(method.isAnnotationPresent(Check.class)){
//有Check就执行
try {
method.invoke(c);//现在是通过Calss对象的Method对象method来调用类中invoke()调用c对象方法
} catch (Exception e) {
//如果有异常,进行捕获并写入bug.txt中
count++;
bw.write(method.getName() + "方法出现了异常!");
bw.newLine();//换行
bw.write("异常的名称:" + e.getClass().getSimpleName());
bw.newLine();//换行
bw.write("异常原因:" + e.getCause().getMessage());
bw.newLine();//换行
}
}
}
bw.write("本次测试一共出现:" + count + "次异常");
bw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}