? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 面試遇梗
一次面試,面試官問:“你能說說什么是AOP嗎涵但?”
“AOP就是面向切面編程”杈绸,然后沒有了帖蔓,好簡短的描述,自己都覺得少瞳脓。如果面向對象是縱向的塑娇,那么面向切面就是橫向的,心里想著切豆腐的模樣劫侧,可是并沒有說出埋酬,自己對AOP的理解還存在理論上,不敢多說烧栋,言多必失呀写妥。
“AOP都能做些什么?”审姓,面試官的目光帶著些期盼珍特,希望能夠回答得多一些。
“記錄日志呀”魔吐,還是扎筒,還是那么一句話。這一句話也是道聽途說的酬姆,用AOP來做日志砸琅,Spring的書看過了好幾遍,也沒有記住什么精華轴踱,到底是用的少症脂。天天寫代碼,都寫的什么玩意淫僻,沒長腦子就寫了吧诱篷,自己也忍不住罵了自己幾句。
越回答越精簡雳灵,面試官都不知再如何開口問起棕所,比擠牙膏難多了。面試就這樣在尷尬中戛然而止悯辙。別人面試都那么久琳省,自己面試保證是最快的一個,半個小時都沒有躲撰,哎针贬。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 反? 思
翻翻資料,Spring框架發(fā)展至今也有六七個年頭了拢蛋,作為Spring的兩大特性之一桦他,AOP面向切面編程思想,為什么一直是個亮點谆棱,為什么會引起那么多開發(fā)人員的狂愛呢快压。
最近在使用SpringCloud框架圆仔,想做個日志,什么樣的日志呢蔫劣,就是對用戶的一舉一動做日志坪郭,某年某月某某某做了某某操作,當然脉幢,這個可不能對用戶說截粗,這些是為后期大數(shù)據(jù)統(tǒng)計用的。想想以前做項目鸵隧,要么沒有日志绸罗,要么是在業(yè)務邏輯里手動加log,那么多處理業(yè)務邏輯的類豆瘫,加起來那個辛苦珊蟀、那個痛苦,回憶起來外驱,老淚縱橫呀育灸。
為了避免這個痛苦,一定要痛改前非昵宇,狠下心來磅崭,靜靜地研究AOP,有什么難的呢瓦哎,別人能用的砸喻,自己也能用。不用則以蒋譬,一用不得了割岛,啊,啊犯助,啊癣漆,果真是真愛。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 一用鐘情
先分析一下剂买,自己的需求惠爽,需要在每個Controller層,增加一次注解瞬哼,用來做日志婚肆,然后在每個方法調用時,產(chǎn)生日志倒槐。是的旬痹,需求就是這么簡單,已經(jīng)拆解過了讨越,只需三步两残。第一步,需要一個添加日志的注解把跨;第二步人弓,往需要的方法上增加注解;第三步着逐,監(jiān)控每個方法崔赌,通過注解獲取方法,并生成日志記錄到數(shù)據(jù)庫保存耸别。
第一步健芭,注解類定義
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 "";
}
第二步,執(zhí)行方法上增加注解
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);
}
}
第三步省有,監(jiān)控方法類
/**
* 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");
? ? //獲取被執(zhí)行的方法
? ? 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());
? ? }?
? ? }? ?
? ? }
}
最后執(zhí)行以下http://localhost:8701/test/1,可以看到控制臺有輸出:
今天蠢沿,終于可以用AOP面向切面編程的思想來做日志記錄了伸头,內心里竊喜,忍不住雀躍了一下舷蟀,AOP太好用了恤磷,AOP,愛死你了野宜。