前言:鉴于前两天面试,让实现一个自定义注解的面试题卡住,及扩展Spring注解怎么实现的问题。在此先把实现自定义注解这部分,把以前代码中写过的一个简单的例子,记录一下。
1、定义一个自定义注解
package com.example.demo.aop;
import java.lang.annotation.*;
/**
* @author jushisi
* @description 自定义注解用于AOP拦截标识
*/
@Retention(RetentionPolicy.RUNTIME) // 表示注解在运行时依然存在
@Target(ElementType.METHOD)
@Documented
public @interface AopLog {
}
2、AOP读取注解,做具体操作
利用@annotation(com.example.demo.aop.AopLog)读取
package com.example.demo.aop;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSON;
/**
* @author jushisi
* @description TODO AOP为啥不能成功调用所有方法 有点奇怪 待研究
*/
@Component
@Aspect
public class HttpAspect {
private static final Logger logger = LoggerFactory.getLogger(HttpAspect.class);
// @Pointcut("execution(* com.example.demo.controller..*.*(..)) && @annotation(com.example.demo.aop.AopLog)")
@Pointcut("@annotation(com.example.demo.aop.AopLog)")
public void log(){
}
/**
* @description 注意使用ProceedingJoinPoint proceed()
* @author jushisi
*/
@Around("log()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info("@Around:在建议方法调用之前和之后,执行通知。");
joinPoint.proceed();
logger.info("@Around:在建议方法调用之前和之后,执行通知。");
}
/**
* @description 没有环绕通知时 调用
* @author jushisi
*/
@Before("log()")
public void before(JoinPoint joinPoint){
ServletRequestAttributes attributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request =attributes.getRequest();
logger.info("@Before:在一个方法执行之前,执行通知。");
}
/**
* @description 没有环绕通知时 调用
* @author jushisi
*/
@After("log()")
public void after(){
logger.info("@After:在一个方法执行之后,不考虑其结果,执行通知。");
}
/**
* @description 没有环绕通知时 方法执行成功时调用
* @author jushisi
*/
@AfterReturning(pointcut = "log()",returning = "obj")
public void afterReturning(Object obj){
logger.info("@AfterReturning:在一个方法执行之后,只有在方法成功完成时,才能执行通知。");
logger.info("@AfterReturning:"+ JSON.toJSONString(obj));
}
/**
* @description 没有环绕通知时,抛异常时调用 ; 有环绕通知时,即使抛异常也不调用
* @author jushisi
*/
@AfterThrowing(pointcut = "log()", throwing = "ex")
public void afterThrowing(Exception ex){
logger.info("@AfterThrowing:在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。");
}
}
3、调用注解的地方
package com.example.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.aop.AopLog;
/**
* @author jushisi
* @description AopTest
*/
@RestController
@RequestMapping("/aop")
public class AopTest {
private static final Logger logger = LoggerFactory.getLogger(AopTest.class);
@RequestMapping("/exception")
@AopLog
public String exception(Integer num){
logger.info(String.valueOf(1/num));
return "exception";
}
@RequestMapping("/test")
@AopLog
public String test(Integer num){
String str = "AOP function test ......";
logger.info(str);
return str;
}
}
自定义注解与AOP实战

本文介绍如何创建自定义注解并结合Spring AOP进行应用。通过定义注解、配置切面类以及在控制器中使用注解,实现方法执行前后的日志记录功能。
1457

被折叠的 条评论
为什么被折叠?



