java註解原理——記錄一下自己的理解

最近因爲系統可能要更換成java語言,於是每天都在拼命的研究java的相關知識和框架。之前學習註解的時候,沒有太深入的去理解它,只是覺得標註一下挺好用,但是現在在學到spring aop的時候,突然發現註解的功能是如此強大。不得已,只好仔細來研究一下註解的原理性問題了。

首先,網上有各種介紹註解是運用反射機制,但是我相信很多人其實並不熟練運用反射,當然我這個菜鳥更是如此。但好在反射雖並不常用,但是很好理解。而註解就顯得繞口很多。

言歸正傳,現在開始用我那白的不能再白的大白話跟大家講解一下了(畢竟這個行業總是喜歡搞一些裝逼的高大上的詞彙)。

爲了更好的向大家解釋,我還是先貼代碼吧(大家直接copy到自己的IDE上去跑就好)。

BusinessLogic.java
package annotationTest;
/** * @author  kalson 
    * @date 創建時間:2017年11月7日 下午1:13:14 
    * @version 1.0 
    */
public class BusinessLogic {
    public BusinessLogic() {
        super();
    }
    
    public void compltedMethod() {
        System.out.println("This method is complete");
    }    
    
    @Todo(priority = Todo.Priority.HIGH)
    public void notYetStartedMethod() {
        // No Code Written yet
    }
    
    @Todo(priority = Todo.Priority.MEDIUM, author = "Uday", status = Todo.Status.STARTED)
    public void incompleteMethod1() {
        //Some business logic is written
        //But its not complete yet
    }

    @Todo(priority = Todo.Priority.LOW, status = Todo.Status.STARTED )
    public void incompleteMethod2() {
        //Some business logic is written
        //But its not complete yet
    }
}

Todo
package annotationTest;
/** * @author  kalson 
    * @date 創建時間:2017年11月7日 下午1:12:57 
    * @version 1.0 
    */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Todo {
    public enum Priority {LOW, MEDIUM, HIGH}
    public enum Status {STARTED, NOT_STARTED}    
    String author() default "Yash";
    Priority priority() default Priority.LOW;
    Status status() default Status.NOT_STARTED;
}

TodoReport 
package annotationTest;
/** * @author  kalson 
    * @date 創建時間:2017年11月7日 下午1:13:27 
    * @version 1.0 
    */

import java.lang.reflect.Method;

public class TodoReport {
    public TodoReport() {
        super();
    }

    public static void main(String[] args) {
        getTodoReportForBusinessLogic();
    }

    /**
     * This method iterates through all messages of BusinessLogic class and fetches annotations defined on each of them.
     * After that it displays the information from annotation accordingly.
     */
    private static void getTodoReportForBusinessLogic() {
        
        Class businessLogicClass = BusinessLogic.class;
        for(Method method : businessLogicClass.getMethods()) {
            Todo todoAnnotation = (Todo)method.getAnnotation(Todo.class);
            if(todoAnnotation != null) {
                System.out.println(" Method Name : " + method.getName());
                System.out.println(" Author : " + todoAnnotation.author());
                System.out.println(" Priority : " + todoAnnotation.priority());
                System.out.println(" Status : " + todoAnnotation.status());
                System.out.println(" --------------------------- ");
            }
        }
    }
}

創建了三個類,一個BusinessLogic.java,要被註解的類

一個Todo.java,註解類

一個TodoReport ,測試類。

註解機制最終要的運用了反射機制就是由於如下代碼部分

 Class businessLogicClass = BusinessLogic.class;

這個Class 的運用想必大家見過但是並沒有認真理解過。所謂的類的類創建,說起來比較拗口,但是我舉一個不恰當的例子。

理念一:假設把克隆當作java中new實例對象的過程,那麼這個模型就是我們自己創建的類,但是克隆的原型其實並不是最底層,底層而是細胞,所以如果你想new一個對象,那你就需要先把這個模型new出來,而註解就是作用在這個過程,也就是說,JVM識別註解是在創建模型類的時候就開始識別了。

理念二:其次,需要再跟大家解釋的一個問題就是,套用網上內容Annotations僅僅是元數據,和業務邏輯無關。所以,如果你在學習AOP等各種框架的時候,時刻想着,它的邏輯部分都是框架來實現的,暴露給用戶的都只是一些標誌點而已。至於邏輯部分,只好大家發揮腦洞,自己去猜測了。

==========================================================================================

有了上面兩點理念之後,現在我們再來看一下一個用到spring框架的例子。

@Aspect   --說明這是一個切面類
public class Logging {

	@Pointcut("execution(* com.yiibai.*.*(..))")//比如說這個註解,
	JVM啓動開始創建各種類的類對象的時候,就會識別到這個註解,它的邏輯是什麼樣的,由
	spring框架來指定(比如說是對com.yiibai.下的所有類的所有方法都用selectAll做標記)。
	
	private void selectAll() {
	}

//	@Before("@annotation(com.yiibai.Loggable)")
	@Before("selectAll()")//比如說識別到Before這個註解的時候,會對selectAll標記的方法前綁定
	beforeAdvice方法。這也是由spring框架來做的,所以我們看不到。
	public void beforeAdvice() {
		System.out.println("going to setup student profile");
	}

	@After("selectAll()")
	public void afterAdvice() {
		System.out.println("Student profile has been setup.");
	}

//	@AfterReturning("selectAll()")
	public void afterReturningAdvice(Object retval) {
		System.out.println("returing" + retval.toString());
	}

//	@AfterThrowing("selectAll()")
	public void afterThrowingAdvice(IllegalArgumentException ex) {
		System.out.println("There has been an exception: " + ex.toString());
	}
}


由於目前只是學習階段,還沒有做對框架的底層研究,所以以上的觀念純屬個人對這方面的抽象理解,希望大家能夠結合自己的知識指正或者希望可以幫助大家理解註解。至於以上註釋中的邏輯,也純屬個人yy的結果。大家感受一下就好

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章