Java之反射獲取Annotation信息


簡介:

在JDK1.5以后提供的一系列Annotation聲明,要通過反射獲取Annotation的信息,可以通過java.lang.reflect里面的AccessibleObject類,在這個類中提供有獲取Annotation的方法.

獲取全部Annotation:

public Annotation[] getAnnotations()

獲取指定Annotation:

public <T extends Annotation> T getAnnotation(Class<T> annotationClass)

import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Method; public class MAIN { public static void main(String[] args) throws Exception { { // 獲取接口上的Annotation信息
            Annotation[] annotations = IMessage.class.getAnnotations();     // 獲取接口上的全部Annotation信息
            for (Annotation annotation : annotations) { System.out.println("IMessage - annotation: " + annotation); } } System.out.println("__________________________________"); { // 獲取Message上的Annotation信息
            Annotation[] annotations = Message.class.getAnnotations();     // 獲取接口上的全部Annotation信息
            for (Annotation annotation : annotations) { System.out.println("Message - annotation: " + annotation);   // 無法在程序執行的時候獲取
 } } System.out.println("__________________________________"); { // 獲取Message.toString()方法上的Annotation信息
            Method method = Message.class.getDeclaredMethod("send",String.class);     // 獲取Message中的指定方法
            Annotation[] annotations = method.getAnnotations();     // 獲取指定方法的Annotation信息
            for (Annotation annotation : annotations) { System.out.println("Message.send() - annotation: " + annotation);   // 無法在程序執行的時候獲取
 } } } } @FunctionalInterface @Deprecated(since = "1.0") interface IMessage{     // 兩個Annotation
    void send(String msg); } @SuppressWarnings("serial") // 無法在程序執行的時候獲取
class Message implements IMessage, Serializable { @Override // 無法在程序執行的時候獲取
    public void send(String msg) { System.out.println("sendMessage: " + msg); } @Override public String toString(){ return "toString"; } }

輸出結果:

從運行直接我們可以發現,有些Annotation是可以獲取的,而有些Annotation是無法獲取的;

不同的Annotation是有不同的存在范圍的,對比兩個Annotation:

@FunctionalInterface(運行時生效)

@SuppressWarnings(源代碼時生效

@Documented @Retention(RetentionPolicy.RUNTIME)  // 運行時生效 @Target(ElementType.TYPE) public @interface FunctionalInterface {}

 

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE}) @Retention(RetentionPolicy.SOURCE)  // 源代碼時生效 public @interface SuppressWarnings { String[] value(); }

 

 

"RetentionPolicy" : 指的是生效范圍

public enum RetentionPolicy {
    SOURCE,
    CLASS,
    RUNTIME
}

三個范圍分別是:

  SOURCE:源代碼的時候

  CLASS:類定義的時候

  RUNTIME:運行的時候

 

實現自定義的Annotation:

在java中提供有"@interface"進行自定義Annotation的語法;

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; @Retention(RetentionPolicy.RUNTIME) // 定義Annotation的運行策略
@interface DefaultAnnotation{   // 自定義的Annotation
    public String title();  // 獲取數據
    public String url() default "www.baidu.com";    // 獲取數據,默認值
} class Message{ @DefaultAnnotation(title = "AAA") public void send(String msg){ System.out.println("sendMessage - " + msg); } } public class MAIN { public static void main(String[] args) throws Exception { Method method = Message.class.getMethod("send", String.class); DefaultAnnotation an = method.getAnnotation(DefaultAnnotation.class); System.out.println("title - " + an.title());    // 直接調用annotation中的方法
        System.out.println("url - " + an.url());    // 直接調用annotation中的方法
        String msg =  "msg - " + an.title() + "(" + an.url() + ")"; // 消息內容
        method.invoke(Message.class.getDeclaredConstructor().newInstance(),msg); } }

輸出結果:

Annotation的特點:

   結合反射機制實現程序的處理;

 

Annotation與工廠設計:

以下是動態工廠設計進行消息發送:

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MAIN { public static void main(String[] args) { MessageService mss = new MessageService(); mss.send("www.baidu.com"); } } interface IMessage{ public void send(String msg); } class MessageService{ private IMessage message; public MessageService(){ this.message = Factory.getInstance(Message.class); } public void send(String msg){ this.message.send(msg); } } class Message implements IMessage { @Override public void send(String msg) { System.out.println("sendMessage - " + msg); } } class Factory{ private Factory() { } @SuppressWarnings("unchecked") public static <T> T getInstance(Class<T> clazz){    // 直接返回實例化的操作對象
        try { return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance()); } catch (Exception e) { e.printStackTrace(); return null; } } } class MessageProxy implements InvocationHandler{ private Object target; public MessageProxy() { } public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } public boolean connect(){ System.out.println("【代理操作】- 通道連接"); return true; } public boolean close(){ System.out.println("【代理操作】 - 通道關閉"); return false; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (this.connect()) { return method.invoke(this.target, args); } else { throw new Exception("【ERROR】消息發送失敗!"); } }finally { this.close(); } } }

輸出結果:

下面利用Annotation實現類的使用:

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MAIN { public static void main(String[] args) { MessageService mss = new MessageService(); mss.send("www.baidu.com"); } } @Retention(RetentionPolicy.RUNTIME) @interface UserMessage{ public Class<?> clazz(); } interface IMessage{ public void send(String msg); } @UserMessage(clazz = Message.class) // 利用Annotation實現了類
class MessageService{ private IMessage message; public MessageService(){ UserMessage use = MessageService.class.getAnnotation(UserMessage.class); this.message = (IMessage) Factory.getInstance(use.clazz());     // 直接通過Annotation獲取
 } public void send(String msg){ this.message.send(msg); } } class Message implements IMessage { @Override public void send(String msg) { System.out.println("sendMessage - " + msg); } } class Factory{ private Factory() { } @SuppressWarnings("unchecked") public static <T> T getInstance(Class<T> clazz){    // 直接返回實例化的操作對象
        try { return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance()); } catch (Exception e) { e.printStackTrace(); return null; } } } class MessageProxy implements InvocationHandler{ private Object target; public MessageProxy() { } public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } public boolean connect(){ System.out.println("【代理操作】- 通道連接"); return true; } public boolean close(){ System.out.println("【代理操作】 - 通道關閉"); return false; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (this.connect()) { return method.invoke(this.target, args); } else { throw new Exception("【ERROR】消息發送失敗!"); } }finally { this.close(); } } }

輸出結果:

 

那么這樣就實現了使用Annotation來參與程序設計,只管一點可以從下面的代碼看出:

增加一個NetMessage子類:

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MAIN { public static void main(String[] args) { MessageService mss = new MessageService(); mss.send("www.baidu.com"); } } @Retention(RetentionPolicy.RUNTIME) @interface UserMessage{ public Class<?> clazz(); } interface IMessage{ public void send(String msg); } @UserMessage(clazz = NetMessage.class) // 利用Annotation實現了類的使用
class MessageService{ private IMessage message; public MessageService(){ UserMessage use = MessageService.class.getAnnotation(UserMessage.class); this.message = (IMessage) Factory.getInstance(use.clazz());     // 直接通過Annotation獲取
 } public void send(String msg){ this.message.send(msg); } } class Message implements IMessage { @Override public void send(String msg) { System.out.println("【消息發送】 - " + msg); } } class NetMessage implements IMessage { @Override public void send(String msg) { System.out.println("【網絡消息發送】 - " + msg); } } class Factory{ private Factory() { } @SuppressWarnings("unchecked") public static <T> T getInstance(Class<T> clazz){    // 直接返回實例化的操作對象
        try { return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance()); } catch (Exception e) { e.printStackTrace(); return null; } } } class MessageProxy implements InvocationHandler{ private Object target; public MessageProxy() { } public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } public boolean connect(){ System.out.println("【代理操作】- 通道連接"); return true; } public boolean close(){ System.out.println("【代理操作】 - 通道關閉"); return false; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (this.connect()) { return method.invoke(this.target, args); } else { throw new Exception("【ERROR】消息發送失敗!"); } }finally { this.close(); } } }

輸出結果:

此時就只需要將@UserMessage(clazz = NetMessage.class) 中的參數換一下就行了,通過Annotation中的方法直接對參數進行控制。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM