面试遇梗
一次面试,面试官问:“你能说说什么是AOP吗?”
“AOP就是面向切面编程”,然后没有了,好简短的描述,自己都觉得少。如果面向对象是纵向的,那么面向切面就是横向的,心里想着切豆腐的模样,可是并没有说出,自己对AOP的理解还存在理论上,不敢多说,言多必失呀。
“AOP都能做些什么?”,面试官的目光带着些期盼,希望能够回答得多一些。
“记录日志呀”,还是,还是那么一句话。这一句话也是道听途说的,用AOP来做日志,Spring的书看过了好几遍,也没有记住什么精华,到底是用的少。天天写代码,都写的什么玩意,没长脑子就写了吧,自己也忍不住骂了自己几句。
越回答越精简,面试官都不知再如何开口问起,比挤牙膏难多了。面试就这样在尴尬中戛然而止。别人面试都那么久,自己面试保证是最快的一个,半个小时都没有,哎。
反 思
翻翻资料,Spring框架发展至今也有六七个年头了,作为Spring的两大特性之一,AOP面向切面编程思想,为什么一直是个亮点,为什么会引起那么多开发人员的狂爱呢。
最近在使用SpringCloud框架,想做个日志,什么样的日志呢,就是对用户的一举一动做日志,某年某月某某某做了某某操作,当然,这个可不能对用户说,这些是为后期大数据统计用的。想想以前做项目,要么没有日志,要么是在业务逻辑里手动加log,那么多处理业务逻辑的类,加起来那个辛苦、那个痛苦,回忆起来,老泪纵横呀。
为了避免这个痛苦,一定要痛改前非,狠下心来,静静地研究AOP,有什么难的呢,别人能用的,自己也能用。不用则以,一用不得了,啊,啊,啊,果真是真爱。
一用钟情
先分析一下,自己的需求,需要在每个Controller层,增加一次注解,用来做日志,然后在每个方法调用时,产生日志。是的,需求就是这么简单,已经拆解过了,只需三步。第一步,需要一个添加日志的注解;第二步,往需要的方法上增加注解;第三步,监控每个方法,通过注解获取方法,并生成日志记录到数据库保存。
第一步,注解类定义
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 日志注解类
* @author 程就人生
* Target 目标为方法
*
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
// 请求名称
String controllerName() default "";
// 模块名称
String module() default "";
// 请求方式 GET、POST、PUT、DELETE
String actionType() default "";
}
第二步,执行方法上增加注解
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.annotation.LogAnnotation;
/**
* 测试类
* @author 程就人生
*
*/
@RestController
public class TestController {
@GetMapping("/test/{id}")
@LogAnnotation(controllerName="测试Controller", module="测试模块", actionType="GET")
public ResponseEntity<String> test(@PathVariable int id){
String str = "Hello world~!";
//定义头部消息
HttpHeaders headers = new HttpHeaders();
if(id !=1 ){
throw new RuntimeException("aaaaaa");
}else{
headers.add("success", "true");
}
//返回到前端
return new ResponseEntity<>(str, headers, HttpStatus.OK);
}
}
第三步,监控方法类
/**
* Log注入,记录日志
* @author 程就人生
*
*/
@Aspect
@Component
public class LogAop {
/** * 连接点拦截 * @param joinPoint */
@Before("execution(* com.example.demo.controller..*(..))")
public void setLog(JoinPoint joinPoint) {
//获取当前登录用户
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
User user = (User) request.getSession().getAttribute("user");
//获取被执行的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
//获取注解中的名称
LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
if(logAnnotation!=null){
//记录日志
System.out.println("请求模块" + logAnnotation.module());
System.out.println("Controller名称:" + logAnnotation.controllerName());
System.out.println("请求类型:" + logAnnotation.actionType());
//用户信息
if(user != null){
//System.out.println(user.getUserName());
}
}
}
}
最后执行以下http://localhost:8701/test/1,可以看到控制台有输出:
AOP注入输出
今天,终于可以用AOP面向切面编程的思想来做日志记录了,内心里窃喜,忍不住雀跃了一下,AOP太好用了,AOP,爱死你了。
网友评论