从jdk1.5之后,java增加了对元数据的支持,也就是注解。
在我的理解里,自定义注解可以非常友好的解决某些功能模块已经开发好的项目,在不希望改动原有代码的基础上添加某些特定功能的问题。
自定义注解
/**
* 接口日志注解
*/
@Target(ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface LogApi {
/**
* 接口描述信息
* @return
*/
String info();
}
1.@Target(为元注解,是负责注解其他注解的,还有@Retention,@Inherited,@Documented)
用于设定注解的使用范围,Target通过ElementType来指定注解所使用的枚举集合。
ElementType的定义:
ElementType.TYPE //类, 接口(包括注释类型)或枚举声明
ElementType.FIELD,//字段声明(包括枚举常量)
ElementType.METHOD //方法
ElementType.PARAMETER //参数
ElementType.CONSTRUCTOR //构造函数
ElementType.LOCAL_VARIABLE //局部变量
ElementType.ANNOTATION_TYPE //注释类型
ElementType.PACKAGE //包
ElementType.TYPE_PARAMETER //类型参数
ElementType.TYPE_USE //类型的使用
2.@Retention
注解滞留的定义 ,通过RetentionPolicy(保留政策)来指定
RetentionPolicy.SOURCE //源文件中保留
RetentionPolicy.CLASS //记录在类文件中,不需要在运行时由VM保留(默认)
RetentionPolicy.RUNTIME //在运行时由VM保留,因此它们可以被反射地读取
3.@Inherited
指明该注解类型被自动继承。如果一个注解被@Inherited修饰,则该注解作用的类的子类也会使用该注解。
4.@Documented
指示一个类型的注释将由JavaDoc和类似的工具默认记录。此类型应用于注释其注释影响其客户端使用注释元素的类型的声明。如果一个类型声明被注释并被记录,它的注释就成为注释元素的公共API的一部分。
解析注解
通过spring的aop特性来解析注解
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
*通过aop来解析LogApi
*/
@Component
@Aspect
public class LogHandler {
//定义切面,UserController下的所有方法
@Pointcut("execution(* com.springboot.first.controller.UserController.*(..))")
public void logApiPointCut(){
}
@Around("logApiPointCut()")
public Object doAround(ProceedingJoinPoint point) throws Throwable {
Signature signature = point.getSignature();
Method method = ((MethodSignature)signature).getMethod();
LogApi logApi = method.getAnnotation(LogApi.class); //获取自定义注解
//执行代码
Object proceed = point.proceed();
if (logApi==null){
return proceed;
}
Object[] params = point.getArgs();
//这里就是对添加自定义注解的方法进行操作,根据项目具体需求来
System.out.println("在"+method.getName()+"方法上添加了注解,方法参数为"+Arrays.toString(params)+",注解内容是:"+logApi.info());
return proceed;
}
}
在UserController中添加自定义注解:
@RequestMapping("/login")
@LogApi(info = "用户登陆")
public String login(String loginName, String password, Model model){
User user = userService.getUserByLogin(loginName,password);
if(user==null){
model.addAttribute("emg","用户名或密码错误,请重新登录");
return "login";
}
session.setAttribute("user",user);
return "index";
}
测试结果: