1. 概要
- 格式
public @interface 注解名称{
属性列表;
}
- 使用位置:详见 @Target;
- 级别:和 类、接口、枚举 属于同一级别;
- 实质:能被程序所理解,且为当前读取该注释的程序提供判断依据的注释或标签;
- 应用:Annotation 是一个辅助类,在 Junit、Struts、Spring 等工具框架中被广泛使用;
- 注解的“铁三角”关系:定义注解、使用注解、读取注解,欠缺任何一环,都无法发挥注解的真正作用;
分类:大致可分为 自定义注解、JDK内置注解、还有第三方框架提供的注解 三类;
2. JDK 内置注解
2.1 标准注解
@Override - 只能标注方法,表示该方法覆盖父类中的方法,检查该方法是否是重载方法,如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误;
- @Deprecated - 标记过时方法,所标注内容不再被建议使用,如果使用该方法,会报编译警告;
- @SuppressWarnings - 指示编译器去忽略注解中声明的警告;
- @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告;
- @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口;
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次;
2.2 元注解
作用在注解上的注解,所在包 java.lang.annotation;
- @Retention :用于描述注解的生命周期(即:被描述的注解在什么范围内有效),并由编译器存储到指定位置,可有可无,默认 class;
- RetentionPolicy:Enum 枚举类型,用于指定 Annotation 的作用生命域;
- SOURCE:仅存在于编译器处理期间,如” @Override”;
- CLASS:存储于类对应的 .class 文件中,为 Annotation 的默认行为;
- RUNTIME:存储于 class 文件中,并且可由JVM读入;
- RetentionPolicy:Enum 枚举类型,用于指定 Annotation 的作用生命域;
- @Documented :标记这些注解是否包含在用户文档 JavaDoc 中,可有可无;
- @Target - 标记这个注解应该是哪种 Java 成员,可有可无,若无说明可使用于任何地方;
- ElementType:Enum 枚举类型,用于指定注解声明的位置;
- TYPE:类、接口(包括注释类型)或枚举声明;
- FIELD:字段声明(包括枚举常量);
- METHOD:方法声明;
- PARAMETER:参数声明;
- CONSTRUCTOR: 构造方法声明;
- LOCAL_VARIABLE:局部变量声明;
- ANNOTATION_TYPE:注释类型声明 ;
- PACKAGE;
- ElementType:Enum 枚举类型,用于指定注解声明的位置;
@Inherited :某个被标注的类型是被继承的,只能被用来标注“Annotation类型”,如果父类具有该注解,那么其子类也具有该注解;
2.3 延伸
2.3.1 Annotation 类
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
每1个 Annotation 对象,都会有唯一的 RetentionPolicy 属性;
- 对于每 1 个 Annotation 对象,可以有若干个 ElementType 属性;
Annotation 的每一个实现类,都 “和 1 个 RetentionPolicy 关联” 并且 “ 和 1~n 个 ElementType 关联”;
3. Spring 框架常用注解
3.1 Bean 相关注解
@Inject
- @Bean
- Bean 类型描述注解
- @Component :标准一个普通的 spring Bean 类;
- @Repository:标注一个 DAO 组件类;
- @Service:标注一个业务逻辑组件类;
- @Controller:标注一个控制器组件类;
说明
类型
- @Autowired:属于 Spring 的 org.springframework.beans.factory.annotation 包下,可用于为类的属性、构造器、方法注入 Bean;
- @Qualifier:@Autowired 注解默认按照类型装配,如果容器中包含多个同一类型的 Bean,那么启动容器时会报找不到指定类型 Bean 的异常,使用 @Qualifier 进行限定,指定注入的 Bean名称
- @Resource:功能与@Autowired 一致,开发中推荐使用 @Resource;
- @PostConstruct 和 @PreDestroy 方法:实现初始化和销毁 bean 之前进行的操作;
- @Autowired:属于 Spring 的 org.springframework.beans.factory.annotation 包下,可用于为类的属性、构造器、方法注入 Bean;
说明
@Autowired 与 @Resource 的区别
- 提供方: @Autowired 是 Spring 注解;而 @Resource 是 javax.annotation 注解,来自于 JSR-250,J2EE 提供,需要 JDK1.6 及以上;
- 注入方式: @Autowired 只按照 Type 注入;@Resource 默认按 Name 自动注入,也提供按照 Type 注入;
- 属性:@Autowired 在默认情况下,要求其依赖的 bean 对象必须存在,否则需设置其 required 属性为false;@Resource 会优先以 name 寻找依赖 bean 对象,若无设置 name,则会默认类、字段或方法名称为 bean 名称,只有在依赖 name 无法找到依赖对象时,才会回退到按 type 寻找;
3.3 配置文件注解
@EnableConfigurationProperties
- @Configuration
- @Value
- @ConfigurationProperties
- @AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder
- @ContextConfiguration
- @Import
- @ImportResource
- @Required
- @PropertySource
3.4 事务模块注解
类型
- @EnableTransactionManagement
@Transactional:在处理dao层或service层的事务操作时,譬如删除失败时的回滚操作
3.5 AOP 相关注解
@EnableAspectJAutoProxy
@Aspect
@PointCut
@Before、@Around、@After
@AfterReturning
@AfterThrowing3.6 缓存相关注解
@EnableCaching
@SessionAttributes
@Cacheable
@CacheEvict3.7 Spring MVC 注解
@Controller :表明该类会作为与前端作交互的控制层组件,通过服务接口定义的提供访问应用程序的一种行为,解释用户的输入,将其转换成一个模型然后将试图呈献给用户;
- @RequestMapping : 将 url 映射到整个处理类或者特定的处理请求的方法,既可以作用在类级别,也可以作用在方法级别,允许只使用通配符;
- @RequestBody : @RequestBody是指方法参数应该被绑定到HTTP请求Body上。@ResponseBody与@RequestBody类似,它的作用是将返回类型直接输入到HTTP response body中。
- @RequestParam :将请求的参数绑定到方法中的参数上,有 required 参数,且默认为 true,若不要求参数必须要传,需设定 required 为 false;
- @PathVariable : 用于修饰方法的参数,将其变为可供使用的 url 变量(可用于动态绑定);
- @RestController :控制器实现了REST的API,只为服务于JSON,XML或其它自定义的类型内容,@RestController用来创建REST类型的控制器,与@Controller类型。@RestController就是这样一种类型,它避免了你重复的写@RequestMapping与@ResponseBody
- @ModelAttribute :@ModelAttribute可以作用在方法或方法参数上,当它作用在方法上时,标明该方法的目的是添加一个或多个模型属性(model attributes)
说明
@Controller
@RequestMapping("/happy")
public class HappyController {
@Autowired
private HappyService happyService;
@RequestMapping(/hello/*)
public void sayHello(){
//请求为 /happy/hello/* 都会进入这个方法!
//例如:/happy/hello/123 /happy/hello/adb
//可以通过get/post 请求
}
@RequestMapping(value="/haha",method=RequestMethod.GET)
public void sayHaHa(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "age", required = true) String age
){
//只能通过get请求
@RequestMapping(value="/happy/{dayid}",method=RequestMethod.GET)
public String findPet(@PathVariable String dayid, Model mode) {
//使用@PathVariable注解绑定 {dayid} 到String dayid
}
}
...
}
3.8 Mybatis相关注解
可支持数据类型
- 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
- String类型
- Class类型
- enum类型
- Annotation类型
- 以上所有类型的数组
- 访问权修饰符:只能用 public 或 默认(default);
- 注解参数必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为 null,惯用做法是使用 空字符串、0 或负数;
如果只有一个参数成员,最好把参数名称设为”value”,eg:String value() default “”,使用时无需声明;
若有多个参数成员,则在使用时必须要声明对哪个参数初始化,即 参数名 = xxx;
5. 注解处理器(反射)
// 首先自定义一个注解
@Documented
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
String getValue() default "no description";
}
// 使用
@MyAnnotation1(getValue = "annotation on class")
public class Demo1 {
@MyAnnotation1(getValue = "annotation on field")
public String name;
@MyAnnotation1(getValue = "annotation on method")
public void hello(){}
@MyAnnotation1()
public void defaultMethod(){}
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
Class<Demo1> clazz = Demo1.class;
// 获取类上的注解
MyAnnotation1 annotationOnClass = clazz.getAnnotation(MyAnnotation1.class);
System.out.println(annotationOnClass.getValue());
// 获取字段上的注解
Field name = clazz.getField("name");
MyAnnotation1 annotationOnField = name.getAnnotation(MyAnnotation1.class);
System.out.println(annotationOnField.getValue());
// 获取方法上的注解
Method hello = clazz.getMethod("hello", null);
MyAnnotation1 annotationOnMethod = hello.getAnnotation(MyAnnotation1.class);
System.out.println(annotationOnMethod.getValue());
// 获取默认注解
Method defaultMethod = clazz.getMethod("defaultMethod", null);
MyAnnotation1 annotationOnDefaultMethod = defaultMethod.getAnnotation(MyAnnotation1.class);
System.out.println(annotationOnDefaultMethod.getValue());
}
}
参考