關(guān)于對(duì)Spring自帶的注解的疑惑

按照我的理解迈勋,Spring的注解是一個(gè)標(biāo)簽醋粟,為的是標(biāo)注一下某個(gè)方法(目前我所經(jīng)歷的注解應(yīng)用的最多的就是在方法名上)重归,然后在某個(gè)地方找到有這個(gè)標(biāo)記的方法,對(duì)這些方法做一些自定義的處理鼻吮。

現(xiàn)在知道在我們項(xiàng)目中自定義的注解的處理方法的實(shí)現(xiàn)是通過寫切面來實(shí)現(xiàn)的椎木,比如有個(gè)@Log注解博烂,它可以把一些關(guān)鍵點(diǎn)的日志保存到數(shù)據(jù)庫(kù)里漱竖。于是就定義了一個(gè)切面,切面會(huì)找到被這個(gè)標(biāo)簽標(biāo)注的類馍惹,然后為它們保存日志信息万矾。

import java.lang.annotation.Retention;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value() default "";
}

import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import com.kyee.common.service.LogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.kyee.common.annotation.Log;
import com.kyee.common.domain.LogDO;
import com.kyee.common.utils.HttpContextUtils;
import com.kyee.common.utils.IPUtils;
import com.kyee.common.utils.JSONUtils;
import com.kyee.common.utils.ShiroUtils;
import com.kyee.system.domain.UserDO;

@Aspect
@Component
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    LogService logService;


    @Pointcut("@annotation(com.kyee.common.annotation.Log)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // 執(zhí)行方法
        Object result = point.proceed();
        // 執(zhí)行時(shí)長(zhǎng)(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //異步保存日志
        saveLog(point, time);
        return result;
    }

    void saveLog(ProceedingJoinPoint joinPoint, long time) throws InterruptedException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogDO sysLog = new LogDO();
        Log syslog = method.getAnnotation(Log.class);
        if (syslog != null) {
            // 注解上的描述
            sysLog.setOperation(syslog.value());
        }
        // 請(qǐng)求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");
        // 請(qǐng)求的參數(shù)
        Object[] args = joinPoint.getArgs();
        try {
            String params = JSONUtils.beanToJson(args[0]).substring(0, 4999);
            sysLog.setParams(params);
        } catch (Exception e) {

        }
        // 獲取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        // 設(shè)置IP地址
        sysLog.setIp(IPUtils.getIpAddr(request));
        // 用戶名
        UserDO currUser = ShiroUtils.getUser();
        if (null == currUser) {
            if (null != sysLog.getParams()) {
                sysLog.setUserId(-1L);
                sysLog.setUsername(sysLog.getParams());
            } else {
                sysLog.setUserId(-1L);
                sysLog.setUsername("獲取用戶信息為空");
            }
        } else {
            sysLog.setUserId(ShiroUtils.getUserId());
            sysLog.setUsername(ShiroUtils.getUser().getUsername());
        }
        sysLog.setTime((int) time);
        // 系統(tǒng)當(dāng)前時(shí)間
        Date date = new Date();
        sysLog.setGmtCreate(date);
        // 保存系統(tǒng)日志
        logService.save(sysLog);
    }
}

那么Spring的這些注解理應(yīng)在Spring框架中進(jìn)行實(shí)現(xiàn)了后添,比如說RequestMapping這個(gè)注解薪丁,但是點(diǎn)擊進(jìn)去只能看到注解的定義,并不知道它的實(shí)現(xiàn)代碼在哪里.


package org.springframework.web.bind.annotation;

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;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.Mapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}

看到一篇文章:https://dzone.com/articles/spring-annotation-processing-how-it-works

If you see an annotation, there must be some code somewhere to process it.

如果你看到了一個(gè)注解努溃,那么一定在某個(gè)地方有段代碼去處理它阻问。

在InitDestroyBeanPostProcessor類中有下面一段代碼:

private InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata buildLifecycleMetadata(Class<?> clazz) {
        boolean debug = this.logger.isDebugEnabled();
        LinkedList initMethods = new LinkedList();
        LinkedList destroyMethods = new LinkedList();
        Class targetClass = clazz;

        do {
            LinkedList currInitMethods = new LinkedList();
            LinkedList currDestroyMethods = new LinkedList();
            ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
                if(this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
                    InitDestroyAnnotationBeanPostProcessor.LifecycleElement element = new InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method);
                    currInitMethods.add(element);
                    if(debug) {
                        this.logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
                    }
                }

                if(this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
                    currDestroyMethods.add(new InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method));
                    if(debug) {
                        this.logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
                    }
                }

            });
            initMethods.addAll(0, currInitMethods);
            destroyMethods.addAll(currDestroyMethods);
            targetClass = targetClass.getSuperclass();
        } while(targetClass != null && targetClass != Object.class);

        return new InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata(clazz, initMethods, destroyMethods);
    }

根據(jù)反射方法尋找注解標(biāo)記称近,如果找到了注解標(biāo)記,這個(gè)被標(biāo)記的方法被當(dāng)做一個(gè)初始化方法存了下來刨秆。然后就會(huì)調(diào)用所有找到的初始化方法,給對(duì)象執(zhí)行這些操作尸执。

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = this.findLifecycleMetadata(bean.getClass());

        try {
            metadata.invokeInitMethods(bean, beanName);
            return bean;
        } catch (InvocationTargetException var5) {
            throw new BeanCreationException(beanName, "Invocation of init method failed", var5.getTargetException());
        } catch (Throwable var6) {
            throw new BeanCreationException(beanName, "Failed to invoke init method", var6);
        }
    }

隱隱的感覺到是這么處理的缓醋,感覺還沒有理解很透徹,待我繼續(xù)調(diào)查回來再更褪贵。。脆丁。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末槽卫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子晒夹,更是在濱河造成了極大的恐慌,老刑警劉巖喷好,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件读跷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡无切,警方通過查閱死者的電腦和手機(jī)丐枉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來籍嘹,“玉大人,你說我怎么就攤上這事辱士√” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵头岔,是天一觀的道長(zhǎng)贴妻。 經(jīng)常有香客問我,道長(zhǎng)名惩,這世上最難降的妖魔是什么孕荠? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮弯予,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘受楼。我一直安慰自己,他們只是感情好艳汽,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布对雪。 她就那樣靜靜地躺著,像睡著了一般馋艺。 火紅的嫁衣襯著肌膚如雪迈套。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天雏赦,我揣著相機(jī)與錄音芙扎,去河邊找鬼。 笑死戒洼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的圈浇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼召耘,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼褐隆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衫贬,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎梆造,沒想到半個(gè)月后葬毫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镇辉,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忽肛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年栈暇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片煎源。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡香缺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出图张,到底是詐尸還是另有隱情,我是刑警寧澤兽埃,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布适袜,位于F島的核電站,受9級(jí)特大地震影響苦酱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜颂跨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一扯饶、第九天 我趴在偏房一處隱蔽的房頂上張望池颈。 院中可真熱鬧蔓同,春花似錦蹲诀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尚揣。三九已至掖举,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間塔次,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工藕溅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留继榆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓集币,卻偏偏與公主長(zhǎng)得像翠忠,于是被迫代替她去往敵國(guó)和親鞠苟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子负间,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理政溃,服務(wù)發(fā)現(xiàn),斷路器董虱,智...
    卡卡羅2017閱讀 134,633評(píng)論 18 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架申鱼,建立于...
    Hsinwong閱讀 22,358評(píng)論 1 92
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評(píng)論 6 342
  • 又是一年端午捐友。 再也不像清明前后的低暗沉郁和淫雨霏霏溃槐。陽(yáng)光也似乎變得勤奮了,幾乎每天都會(huì)光臨人間昏滴。 家鄉(xiāng)的端午每年...
    仁子閱讀 502評(píng)論 0 1
  • 關(guān)于十二生肖里的排序原因姻几,各種傳說很多,既是傳說蛇捌,就沒有對(duì)或錯(cuò),只是誰更合理而已豁陆。本篇告訴你的是可...
    職業(yè)敬仰者閱讀 813評(píng)論 0 0