注解越来越流行于Web应用中,如果我们可以自定义注解,为我们所用,并完成我们想要的功能,那岂不是件乐事!
这篇博文一共做两件事:
1 . 如何自定义注解?
2 . 如果用注解做有价值的事情?
首先说第一个,注解的定义其实很简单,像类一样,只不过public class XXX 变成了 public
OK,看看这简单的定义:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HelloWorld {
String value();
}
也许有人会问,这些@Target、@Retention、@Documented,都是些啥东东,需要引包吗?很诚恳的告诉你,不需要引包,强大到爆的@JDK同学已经帮我们做了,它们就在java.lang.annotation.*包里。
我们来介绍一下@Target、@Retention、@Document 这三位重量级人物吧。
@Target : 就是注解放到什么地方!ElementType的枚举类型如下:
TYPE : 类、接口或enum声明
FIELD:域(属性)声明
METHOD:方法声明
PARAMETER:参数声明
CONSTRUCTOR:构造方法声明
ANNOTATION_TYPE:注释类型声明
PACKAGE:包声明
@Rentation: 表示需要在什么级别保存该注解信息。RetentionPolicy的枚举类型如下:
SOURCE:注解将被编译器丢弃
CLASS:注解将会被编译至class文件中,但在运行时jvm不保留
RUNTIME:运行时保留注解
@Documented:此注解将包含在javadoc中
如上定义,我们可以这样使用:
@HelloWorld("Hello")
或者:
@HellowWorld(value="Hello")
不可以这样(只有定义中设置default值后才可以):
@HelloWorld
OK,下面我们进入第二个专题,如何用其做有价值的事情?
我们在springweb应用中,需要在服务器启动时,获取所有含有某个注解的类以及方法,让其做一定的事情。
以下代码中,引的package以及所在的package我就不写了,节省点儿空间。
我们先定义一个在类级别上的注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HelloClass {
String value() default "helloClass"
}
其次,方法级别的注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HelloMethod{
String id();
String name();
}
然后,我们如何在服务器启动过程中,做些事情呢?我们来实现ApplicationListener
并覆写onApplicationEvent方法。
public class HelloWorld implements ApplicationListener {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
logger.debug("------初始化执行----");
try {
// 获取上下文
ApplicationContext context = event.getApplicationContext();
// 获取所有beanNames
String[] beanNames = context.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
HelloClass helloClass = context.findAnnotationOnBean(beanName,
HelloClass.class);
//判断该类是否含有HelloClass注解
if (helloClass != null) {
Method[] methods = context.getBean(beanName).getClass()
.getDeclaredMethods();
for (Method method : methods) {
//判断该方法是否有HelloMethod注解
if (method.isAnnotationPresent(HelloMethod.class)) {
HelloMethod helloMethod = method
.getAnnotation(HelloMethod.class);
String id = helloMethod.id();
String name = helloMethod.name();
// do something
logger.debug("注解方法:" + method.getName() + "," + id
+ "," + name);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Ok,在do something注释中,you can do something or everything!