注解早在J2SE1.5就被引入到Java中,主要提供一种机制,这种机制允许程序员在编写代码的同时可以直接编写元数据。
注解可以被用在包,类,方法,变量,参数上。自Java8起,有一种注解几乎可以被放在代码的任何位置,叫做类型注解。
注解会被编译至class文件中,而且会在运行时被处理程序提取出来用于业务逻辑。
当然,创建在运行时不可用的注解也是可能的,甚至可以创建只在源文件中可用,在编译时不可用的注解。
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodInfo{
String author() default "Pankaj";
String date();
int revision() default 1;
String comments();
}
注解方法不能有参数。
注解方法的返回类型局限于原始类型(8中基本数据类型),字符串,枚举,注解,或以上类型构成的数组。
注解方法可以包含默认值。
注解可以包含与其绑定的元注解,元注解为注解提供信息,有四种元注解类型:
1. @Documented
– 表示使用该注解的元素应被javadoc或类似工具文档化,它应用于类型声明,类型声明的注解会影响客户端对注解元素的使用。
如果一个类型声明添加了Documented注解,那么它的注解会成为被注解元素的公共API的一部分。
2. @Target
– 表示支持注解的程序元素的种类,一些可能的值有TYPE, METHOD, CONSTRUCTOR, FIELD等等。
如果Target元注解不存在,那么该注解就可以使用在任何程序元素之上。
3. @Inherited
– 表示一个注解类型会被自动继承,如果用户在类声明的时候查询注解类型,同时类声明中也没有这个类型的注解,
那么注解类型会自动查询该类的父类,这个过程将会不停地重复,直到该类型的注解被找到为止,或是到达类结构的顶层(Object)。
4. @Retention
– 表示注解类型保留时间的长短,它接收RetentionPolicy参数,可能的值有SOURCE, CLASS, 以及RUNTIME。
- @Target用于提示该注解使用的地方,取值有:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
* @since 1.8
*/
TYPE_USE
}
- 分别表示该注解可以被使用的地方:
- 1)类,接口,注解,enum;
- 2)属性域;
- 3)方法;
- 4)参数;
- 5)构造函数;
- 6)局部变量;
- 7)注解类型;
- 8)包
- @Retention用于提示注解被保留多长时间,有三种取值:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
- RetentionPolicy.SOURCE 保留在源码级别,被编译器抛弃(@Override就是此类);
- RetentionPolicy.CLASS被编译器保留在编译后的类文件级别,但是被虚拟机丢弃【默认】;
- RetentionPolicy.RUNTIME保留至运行时,可以被反射读取。
spring的bean容器相关的注解
1)@Autowired 是我们使用得最多的注解,其实就是 autowire=byType 就是根据类型的自动注入依赖(基于注解的依赖注入),可以被使用再属性域,方法,构造函数上。
2)@Qualifier 就是 autowire=byName, @Autowired注解判断多个bean类型相同时,就需要使用 @Qualifier("xxBean") 来指定依赖的bean的id:
@Controller
@RequestMapping("/user")
public class HelloController {
@Autowired
@Qualifier("userService")
private UserService userService;
3)@Resource 属于JSR250标准,用于属性域额和方法上。也是 byName 类型的依赖注入。使用方式:@Resource(name="xxBean"). 不带参数的 @Resource 默认值类名首字母小写。
4)JSR-330标准javax.inject.*中的注解(@Inject, @Named, @Qualifier, @Provider, @Scope, @Singleton)。@Inject就相当于@Autowired, @Named 就相当于 @Qualifier, 另外 @Named 用在类上还有 @Component的功能。
5)@Component, @Controller, @Service, @Repository, 这几个注解不同于上面的注解,上面的注解都是将被依赖的bean注入进入,而这几个注解的作用都是生产bean, 这些注解都是注解在类上,将类注解成spring的bean工厂中一个一个的bean。@Controller, @Service, @Repository基本就是语义更加细化的@Component。
6)@PostConstruct 和 @PreDestroy 不是用于依赖注入,而是bean 的生命周期。类似于 init-method(InitializeingBean) destory-method(DisposableBean)