本人菜雞一個,寫這個系列的文章是爲了通過把自己理解AOP的心路歷程記錄下來,加深自己對這個思想的印象~
背景:
其實一開始聽到AOP這個概念的時候,是自己剛學java沒多久的時候,那時候很懵逼啊,這都什麼鬼啊?
所以寫這篇文章的時候,希望能夠把自己理解的線路描繪出來。
一、我們從代碼簡潔和優化的初衷!
來往後看,理解什麼是AOP思想!
舉個例子,當我們一個java代碼被調用的時候,我想記錄一些指標(其實不就是打印日誌需求)
public void functionA(){
System.out.println("functionA調用開始")
//方法邏輯....
System.out.println("functionA調用結束")
}
很簡單,這樣就可以完成我們的需求。
二、然後我們開始想,如何優化這個功能?
1、不使用System.out.print來打印,想用一些封裝的打印類
當然我們可以自己實現一個打印類,或者使用現有的,比如log4j
private static final Logger logger = LoggerFactory.getLogger(當前類.class);
public void functionA(){
logger.info("functionA調用開始")
//方法邏輯....
logger.info("functionA調用結束")
}
2、甚至我們覺得直接這樣調用不好(想讓打印出來的日誌格式統一),因此我們寫了方法來封裝他
private static final Logger logger = LoggerFactory.getLogger(當前類.class);
public void printLog(String type,String funcName){
if(type=="start"){
logger.info(funcName+"調用開始")
}else{
logger.info(funcName+"調用結束")
}
}
public void functionA(){
printLog("start","functionA")
//方法邏輯....
printLog("end","functionA")
}
public void functionB(){
printLog("start","functionB")
//方法邏輯....
printLog("end","functionB")
}
到此爲止,你已經做出了兩步優化,這是在代碼改動最少的情況下,能做出的最大的優化!
三、有沒有更好的優化方法?
我想要實現那種,只需要寫代碼邏輯,然後日誌這些亂七八糟的東西,我不需要用代碼來指定打印,自動打印就好了。
如果你有這種想法的話,恭喜,AOP就是因爲這種想法誕生的!
這裏暫且不討論在spring中如何使用aop的註解來實現日誌的打印
我們來想想,就上面的那部分代碼如何優化?
-1、做一個抽象類,實現了打印日誌的具體方法,並且留下一個run方法給實現類實現
public abstract class CommonJob {
public Logger logger ;
protected CommonJob( Logger logger) {
this.logger = logger;
}
public void beforeLog(){
logger.info("調用開始")
}
public void afterLog(){
logger.info("調用結束")
}
public void error(){
logger.error("調用失敗")
}
public abstract void run();
}
-2、必須有個地方調用打印日誌和run方法
public class CommonAnalyzer {
public void runJob(CommonJob job){
try{
job.beforeLog();
job.run();
job.afterLog();
} catch (Exception e) {
job.error(e);
}
}
}
-3、然後調用
public class AModelAnalyzer extends CommonAnalyzer {
private static final Logger logger = LoggerFactory.getLogger(當前類.class);
public void functionA(){
runJob(new CommonJob(logger){
@Override
public void run() {
//具體代碼邏輯
//balabalabala....
}
});
}
public void functionB(){
runJob(new CommonJob(logger){
@Override
public void run() {
//具體代碼邏輯
//balabalabala....
}
});
}
public static void main(String[] args){
functionB();
functionA();
}
}
這樣,我們就只需要在調用runJob方法的時候傳入CommonJob類的實現類,或者在runJob中實現一個匿名內部類!
-4、甚至當處理邏輯一樣的時候,我們可以寫一個CommonJob的實現類,這樣就可以複用相同的run代碼,
好比這樣!
public class SelfCommonJob extends CommonJob {
//當有一些處理邏輯一樣的不同模塊的job,
//可以寫一些參數,在run執行的時候做判斷
public SelfCommonJob(Logger logger){
}
//實現run
public void run(){
//代碼邏輯...
}
}
public class AModelAnalyzer extends CommonAnalyzer {
private static final Logger logger = LoggerFactory.getLogger(當前類.class);
private SelfCommonJob scj = new SelfCommonJob (logger);
public void functionA(){
runJob(scj);
}
public void functionB(){
runJob(scj);
}
public static void main(String[] args){
functionB();
functionA();
}
}
當然這只是很基礎的模型,但是這就是AOP的思想,程序員調用這個方法的時候,只需要關注run方法裏面的代碼邏輯就可以了,不需要關注其他打印日誌,判斷執行時間等等一系列的事情!我覺得還是蠻方便的~
好了,這篇文章就到這裏,其實如果是一位java程序員應該對spring中AOP的使用蠻熟悉的,下一篇我會分享下在spring中如何實現這樣的功能,下次再見~
本人菜雞一隻,如果有哪裏寫得不對,或者誤導了大家的,請批評指出,本人一定虛心接受,堅決改正!
也提醒下自己:“驕傲在敗壞以先,狂心在跌倒之前!”