注解是在JDK 1.5后出来的 一种描述数据的元数据
我们先来了解JDK 常用的也是我们经常看见的3个注解
Override Deprecated Suppvisewarnings
其实 @Override 注解主要是用于修饰我们继承父类或者接口中的方法
默认都会给我们加上这个注解 这个注解的意义是:我这个方法是继承或者实现的 如果我们将实现类中所实现的接口的方法删除 那么 实现类就会报错 告诉我们 这个方法必须是实现或者继承过来的。
//接口
public interface AccountDao {
public void outMoney(String out,Double money);
public void inMoney(String in,Double money);
}
//实现类
public class AccountDaoImpl implements AccountDao {
@Override
public void outMoney(String out, Double money) {
}
@Override
public void inMoney(String in, Double money) {
}
}
Deprecated 注解用于标注该方法是否过时 当然过时的方法是可以使用的 但是一般标注过时 肯定会提供新的解决方案.
如果我们将一个方法标注为过时 那么在调用的时候肯定会出现警告告诉我们这个是一个过时的方法 有时候为了忽略警告我们可以使用 @SuppressWarnings 注解 告诉编译器 不检查这个警告。
public interface AccountDao {
public void outMoney(String out,Double money);
@Deprecated
public void inMoney(String in,Double money);
}
@SuppressWarnings("deprecation")
@Override
public void transfer() {
AccountDao a =new AccountDaoImpl();
a.inMoney(in, money);
}
注解分类:
源码注解 运行时注解 编译时注解
源码注解:顾名思义只是在源码中存在 在编译成class文件的时候就不存在了
编译时注解: 注解会存在源码和class文件当中。
@Override @Deprecated @Suppvisewarnings
属于编译时注解
运行时注解: 在运行阶段还好会起作用 比如:
@Autowired 这个就是在运行时会将对象注入进来
按照来源分:我们自定义的注解 第三方注解 JDK自带注解 元注解 四种
自定义注解
使用@interface做关键字
//表示该注解可以修饰的地方 可以包含多个
@Target({ElementType.METHOD,ElementType.TYPE})
//表示该注解 的生命周期
@Retention(RetentionPolicy.RUNTIME)
//表示该注解在生成doc文档的时候保留
@Documented
//@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
@Inherited
public @interface Description {
String name();
String age();
int account() default 100;
}
注解的成员类型是受到限制的合法的类型包括
1.基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String
2.如果注解只有一个成员 则成员必须取名为value 使用可以忽略 value= 直接写值
3.注解类可以没有成员 没有成员的注解称为标识注解
4. 注解成员必须为 无参 无异常抛出 可以使用default做默认值声明
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。
Java5.0定义的元注解:
1.@Target,
2.@Retention,
3.@Documented,
4.@Inherited
@Target: @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention:@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
@Documented:@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
@Inherited: 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类 注意 这种是不支持接口实现的 只是支持继承并且只支持继承类上的注解不支持继承方法上的注解。
如何使用注解:刚刚我们定义了一个注解 并且他的范围是在方法或者接口上都可以使用的那么我们来修饰一个方法
@Description( name = "张三",account=200)
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
我们的类型必须和注解中定义的类型一直 比如 name是String类型
那么使用的时候必须给String类型
age有默认值 如果有默认值我们可以不用给他设置值
如果没有默认值的话就会报错 让你必须把全部给成员赋值.
解析注解:
@Description(name = "李四")
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
private TransactionDefinition txDefinition;
@Autowired
private PlatformTransactionManager txManager;
@SuppressWarnings("deprecation")
@Override
@Description( name = "张三")
public void transfer(final String out, final String in, final Double money) {
AccountDao a =new AccountDaoImpl();
a.inMoney(in, money);
}
}
package com.zs.spring.demo1;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class TransactionTest {
public static void main(String[] args) throws TestExtion{
try {
//通过反射获取class类对象
Class c =Class.forName("com.zs.spring.AccountServiceImpl");
if(c.isAnnotationPresent(Description.class)){
Description d = (Description) c.getAnnotation(Description.class);
System.out.println(d.name());
//获取方法上的注解
Method[] ms = c.getMethods();
for(Method m : ms ){
Annotation[] a = m.getAnnotations();
for(Annotation as: a){
if(as instanceof Description){
Description dm =(Description)as;
System.out.println(d.name());
}
}
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
以上注解的声明周期必须为运行时(RUNTIME) 否则不能将name获取到
因为我们是在运行时对类进行反射 其他级别的生命周期获取不到。