1.常用元注解
Target:注解修饰的对象范围
- METHOD:用于描述
方法
- PACKAGE:用于描述
包
- PARAMETER:用于描述
方法变量
- TYPE:用于描述
类、接口或enum
类型
Retention:注解保留时间长短
- SOURCE:在源文件中有效,编译过程中会被忽略
- CLASS:随源文件一起编译在class文件中,运行时忽略
- RUNTIME:在运行时有效
2.利用反射获取注解信息
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String desc();
int length();
}
public class Test {
@MyAnnotation(desc = "用户名",length = 10)
String username;
@MyAnnotation(desc = "hello方法",length = 100)
public void hello(String msg){
System.out.println("hello:"+msg);
}
@Override
public String toString() {
return "Test{" +
"username='" + username + '\'' +
'}';
}
public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Test test = new Test();
Class<Test> clazz = Test.class;
//获取属性上的注解
Field field = clazz.getDeclaredField("username");
MyAnnotation myAnnotation = field.getDeclaredAnnotation(MyAnnotation.class);
System.out.println("myAnnotation.desc() = " + myAnnotation.desc());
System.out.println("myAnnotation.length() = " + myAnnotation.length());
//获取方法上的注解
Method hello = clazz.getDeclaredMethod("hello", String.class);
MyAnnotation myAnnotation1 = hello.getDeclaredAnnotation(MyAnnotation.class);
System.out.println("myAnnotation1.desc() = " + myAnnotation1.desc());
}
}
结果如下:
myAnnotation.desc() = 用户名
myAnnotation.length() = 10
myAnnotation1.desc() = hello方法
3.自定义注解+拦截器
拦截器:
public class SourceAccessInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle方法在业务处理器处理请求之前被调用");
HandlerMethod method = (HandlerMethod) handler;
LoginRequired loginRequired = method.getMethodAnnotation(LoginRequired.class);
//方法上没有自定义注解
if (loginRequired == null){
return true;
}
//方法上有自定义注解
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("你访问的资源需要先进行登录");
response.flushBuffer();
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle方法在业务处理器处理请求执行完成后,生成视图之前执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion方法在DispatcherServlet完全处理完请求后被调用,可用于清理资源等");
}
}
注册拦截器:
@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("/**");
}
}
web层:
@RestController
public class LoginController {
@LoginRequired
@GetMapping("/a")
public String a(){
System.out.println("你正在访问资源A---前");
System.out.println("a");
System.out.println("你正在访问资源A---后");
return "你正在访问资源A";
}
@GetMapping("/b")
public String b(){
System.out.println("你正在访问资源b---前");
System.out.println("b");
System.out.println("你正在访问资源b---后");
return "你正在访问资源b";
}
}
访问b资源:
访问a资源:
自定义注解+AOP
添加AOP依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
自定义注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}
AOP配置类:
@Aspect
@Component
public class MyLogAspect {
//@annotation表示这个切点在一个注解上,后面带上这个注解的全类名
@Pointcut("@annotation(MyLog)")
public void logPointCut(){
}
@Around("logPointCut()")
public Object logAround(ProceedingJoinPoint joinPoint){
Signature signature = joinPoint.getSignature();
String methodName = signature.getName();
System.out.println("joinPoint.getThis():" + joinPoint.getThis());
System.out.println("joinPoint.getTarget():" + joinPoint.getTarget());
//获取入参
Object[] params = joinPoint.getArgs();
StringBuilder sb = new StringBuilder();
for (Object param : params) {
sb.append(param).append("; ");
}
System.out.println("进入[" + methodName + "]方法,参数为:" + sb.toString());
Object object = null;
try {
//接收方法的返回值
object = joinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
System.out.println(methodName + "方法执行结束");
return object;
}
}
添加web层接口:
@MyLog
@GetMapping(value = "/c/{source_name}")
public String sourceC(@PathVariable("source_name") String sourceName){
System.out.println("你正在访问资源C,sourceName:"+sourceName);
System.out.println("你正在访问资源C---前");
System.out.println("你正在访问资源C---后");
return "你正在访问资源C";
}
打印信息如下:
preHandle方法在业务处理器处理请求之前被调用
joinPoint.getThis():com.fanle.LoginController@3827ed1d
joinPoint.getTarget():com.fanle.LoginController@3827ed1d
进入[sourceC]方法,参数为:helloworld;
你正在访问资源C,sourceName:helloworld
你正在访问资源C---前
你正在访问资源C---后
sourceC方法执行结束
postHandle方法在业务处理器处理请求执行完成后,生成视图之前执行
afterCompletion方法在DispatcherServlet完全处理完请求后被调用,可用于清理资源等