Reflection and Annotation

A reflective and Annotation
  from after JDK1.5, java development provides Annotation technical support, a new model of this technology for the preparation of project brings, after years of development, Annotation of technology has been very widely used, and will already exist in all project development.
- get Annotation: when carrying out a class or method definition can be carried out using a series of Annotation color statement, so if it is to obtain information on these Annotation, then go straight through java.lang.reflect be accomplished inside reflection, there is a class called the AccessibleObject provided in this class has a method of obtaining Annotation:
  Get all Annotation: public Annotation [] getAnnotations ( )
  Gets the specified Annotation: public <T extends Annotation > T getAnnotation (Class <T> annotationClass)
- example: define an interface, and use the Annotation on the interface

. 1  Package . Reflected and the Annotation;
 2  
. 3  Import java.lang.annotation.Annotation;
 . 4  
. 5  / ** 
. 6  * @author : SKY
 . 7  * @version : 0.0.1
 . 8   * / 
. 9  @FunctionalInterface
 10  @Deprecated
 . 11  interface the IMessage {             // There are two annotations annotation 
12 is      public  void Send ();
 13 is  }
 14  
15 @SuppressWarnings ( "Serial" )
 16  class MessageImplthe implements the IMessage {
 . 17      @Override
 18 is      public  void Send () {
 . 19          System.out.println ( "message ..." );
 20 is      }
 21 is  }
 22 is  
23 is  public  class AnnotationDemo {
 24      public  static  void main (String [] args) {
 25          // Get Annotation information on the interface 
26 is          Annotation [] = Annotations the IMessage. class .getAnnotations ();      // get all of the Annotation on the interface 
27          for (Annotation Annotation: Annotations) {
 28             System.out.println(annotation);
29         }
30     }
31 }

--operation result

@java.lang.FunctionalInterface()
@java.lang.Deprecated()

Process finished with exit code 0

- Try to get the implementation class annotation information

 1 public class AnnotationDemo {
 2     public static void main(String[] args) {
 3         //获取接口上的Annotation信息
 4         Annotation[] annotations = IMessage.class.getAnnotations();     //获取接口上的所有的Annotation
 5         for (Annotation annotation : annotations) {
 6             System.out.println(annotation);
 7         }
 8         System.out.println("=========================");
 9         //获取子类上的Annotation
10         Annotation[] implAnnotations = MessageImpl.class.getAnnotations();
11         for (Annotation implAnnotation : implAnnotations) {
12             System.out.println(implAnnotation);
13         }
14     }
15 }

--运行结果

@java.lang.FunctionalInterface()
@java.lang.Deprecated()
=========================

Process finished with exit code 0

--发现并没有获取到注解@SuppressWarnings("serial"),其原因是该注解无法在程序执行的时候获取.那么尝试获取MessageImpl.send()方法上的Annotation会怎么样呢:

 1 public class AnnotationDemo {
 2     public static void main(String[] args) throws NoSuchMethodException {
 3         //获取接口上的Annotation信息
 4         Annotation[] annotations = IMessage.class.getAnnotations();     //获取接口上的所有的Annotation
 5         for (Annotation annotation : annotations) {
 6             System.out.println(annotation);
 7         }
 8         System.out.println("=========================");
 9         //获取子类上的Annotation
10         Annotation[] implAnnotations = MessageImpl.class.getAnnotations();
11         for (Annotation implAnnotation : implAnnotations) {
12             System.out.println(implAnnotation);
13         }
14         //尝试获取MessageImpl.toString()方法上的Annotation
15         System.out.println("==============================");
16         Method send = MessageImpl.class.getDeclaredMethod("send");
17         Annotation[] sendAnnotations = send.getAnnotations();
18         for (Annotation sendAnnotation : sendAnnotations) {
19             System.out.println(sendAnnotation);
20         }
21     }
22 }

--运行结果

@java.lang.FunctionalInterface()
@java.lang.Deprecated()
=========================
==============================

Process finished with exit code 0

--可以发现也无法在运行时获取到 @Override注解的相关信息.不同的Annotation有他的存在的范围:
  @FunctionalInterface:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)      //描述的是运行是生效
    @Target(ElementType.TYPE)
    public @interface FunctionalInterface {}

  @SuppressWarnings("serial"):

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)      //描述的是在源代码时生效
    public @interface SuppressWarnings {
    String[] value();
    }

--可以发现"@FunctionalInterface"是在程序运行时生效的Annotation,所以当程序执行的时候可以获取此Annotation,而"@SuppressWarnings"是在源代码编写的时候有效.管观察RetentionPolicy的定义:

public enum RetentionPolicy {

 

SOURCE,

 

CLASS,

 

RUNTIME
}

--在RetentionPolicy枚举类中还存在一个class的定义指的是在类定义的时候生效.

二.自定义Annotation
  现在已经清楚了Annotation的获取,以及Annotation的运行策略,但是最为关键性的因素是如何可以实现自定义的Annotation.为此在java中提供有新的语法使用"@interface"来定义Annotation.
范例:自定义Annotation

 1 package 反射.反射与Annotation;
 2 
 3 import java.lang.annotation.Retention;
 4 import java.lang.annotation.RetentionPolicy;
 5 import java.lang.reflect.InvocationTargetException;
 6 import java.lang.reflect.Method;
 7 
 8 /**
 9  * @author : S K Y
10  * @version :0.0.1
11  */
12 @Retention(RetentionPolicy.RUNTIME)
13         //定义Annotation运行时的策略
14 @interface DefaultAnnotation {       //自定义的Annotation,
15     public String title();      //获取数据
16 
17     public String url() default "获取数据的默认值";     //获取数据,默认值
18 }
19 
20 class Message {
21     @DefaultAnnotation(title = "sendMessage")   //title不具备默认值,因此必须去显示的定义
22     public void send(String msg) {
23         System.out.println("[消息发送]" + msg);
24     }
25 }
26 
27 public class MyAnnotationDemo {
28     public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
29         Method method = Message.class.getDeclaredMethod("send", String.class);  //获取指定的方法
30         DefaultAnnotation annotation = method.getAnnotation(DefaultAnnotation.class);//获取指定的Annotation1
31         String title = annotation.title();      //直接调用Annotation中的方法
32         String url = annotation.url();
33         System.out.println(title + " " + url);
34         String msg = annotation.title() + " " + url;
35         method.invoke(Message.class.getDeclaredConstructor().newInstance(),msg);        //利用反射实现消息的发送
36     }
37 }

--运行结果

sendMessage 获取数据的默认值
[消息发送]sendMessage 获取数据的默认值

Process finished with exit code 0

--使用Annotation之后的最大特点是可以结合反射机制实现程序的处理.

三.工厂设计模式与Annotation整合
  在清楚了Annotation的整体作用之后,但是Annotation在开发之中,到底可以完成什么样的功能.为了更好的理解Annotation的处理操作的目的,下面将结合工厂设计模式来应用Annotation操作.

 1 package 反射.Annotation与工厂设计模式整合;
 2 
 3 
 4 import java.lang.reflect.InvocationHandler;
 5 import java.lang.reflect.Method;
 6 import java.lang.reflect.Proxy;
 7 
 8 /**
 9  * @author : S K Y
10  * @version :0.0.1
11  */
12 interface IMessage {
13     public void send(String msg);
14 }
15 
16 class MessageImpl implements IMessage {
17     @Override
18     public void send(String msg) {
19         System.out.println("[消息发送]" + msg);
20     }
21 }
22 
23 class MessageProxy implements InvocationHandler {
24     private Object target;
25 
26 
27     public Object bind(Object target) {
28         this.target = target;
29         return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
30     }
31 
32     public boolean connect() {
33         System.out.println("[代理操作]进行消息发送通道的连接");
34         return true;
35     }
36 
37     public void close() {
38         System.out.println("[代理操作]关闭连接通道.");
39     }
40 
41     @Override
42     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
43         try {
44             if (this.connect()) {
45                 return method.invoke(this.target, args);
46             } else {
47                 throw new Exception("[error]消息无法进行发送");
48             }
49         } finally {
50             this.close();
51         }
52     }
53 }
54 
55 class Factory {
56     private Factory() {
57     }
58     public static <T> T getInstance(Class<T> tClass) {       //直接返回一个实例化的操作对象
59         try {
60             return (T) new MessageProxy().bind(tClass.getDeclaredConstructor().newInstance());
61         } catch (Exception e) {
62             e.printStackTrace();
63             return null;
64         }
65     }
66 }
67 class MessageService{
68     private IMessage message;
69 
70     public MessageService() {
71         this.message = Factory.getInstance(MessageImpl.class);
72     }
73     public void send(String msg){
74         this.message.send(msg);
75     }
76 }
77 public class AnnotationFactoryDemo {
78     public static void main(String[] args) throws IllegalAccessException, InstantiationException {
79        MessageService service = new MessageService();
80        service.send("hello");
81 
82     }
83 }

--运行结果

[代理操作]进行消息发送通道的连接
[消息发送]hello
[代理操作]关闭连接通道.

Process finished with exit code 0

--上述代码的实现每次都需要在MessageService类中给出MessageImpl.class的声明,使用注解形式来简化代码

 1 package 反射.Annotation与工厂设计模式整合;
 2 
 3 
 4 import java.lang.annotation.Retention;
 5 import java.lang.annotation.RetentionPolicy;
 6 import java.lang.reflect.InvocationHandler;
 7 import java.lang.reflect.Method;
 8 import java.lang.reflect.Proxy;
 9 
10 /**
11  * @author : S K Y
12  * @version :0.0.1
13  */
14 interface IMessage {
15     public void send(String msg);
16 }
17 
18 class MessageImpl implements IMessage {
19     @Override
20     public void send(String msg) {
21         System.out.println("[消息发送]" + msg);
22     }
23 }
24 
25 class MessageProxy implements InvocationHandler {
26     private Object target;
27 
28 
29     public Object bind(Object target) {
30         this.target = target;
31         return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
32     }
33 
34     public boolean connect() {
35         System.out.println("[代理操作]进行消息发送通道的连接");
36         return true;
37     }
38 
39     public void close() {
40         System.out.println("[代理操作]关闭连接通道.");
41     }
42 
43     @Override
44     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
45         try {
46             if (this.connect()) {
47                 return method.invoke(this.target, args);
48             } else {
49                 throw new Exception("[error]消息无法进行发送");
50             }
51         } finally {
52             this.close();
53         }
54     }
55 }
56 
57 class Factory {
58     private Factory() {
59     }
60     public static <T> T getInstance(Class<T> tClass) {       //直接返回一个实例化的操作对象
61         try {
62             return (T) new MessageProxy().bind(tClass.getDeclaredConstructor().newInstance());
63         } catch (Exception e) {
64             e.printStackTrace();
65             return null;
66         }
67     }
68 }
69 @Retention(RetentionPolicy.RUNTIME)
70 @interface UseMessage{
71     public Class<?> thisClass();
72 }
73 @UseMessage(thisClass = MessageImpl.class)
74 class MessageService{
75     private IMessage message;
76 
77     public MessageService() {
78         UseMessage annotation = MessageService.class.getAnnotation(UseMessage.class);
79         this.message = (IMessage) Factory.getInstance(annotation.thisClass());
80     }
81     public void send(String msg){
82         this.message.send(msg);
83     }
84 }
85 public class AnnotationFactoryDemo {
86     public static void main(String[] args) throws IllegalAccessException, InstantiationException {
87        MessageService service = new MessageService();
88        service.send("hello");
89 
90     }
91 }

--这样我们就可以依据注解来修改整个程序的功能实现.由于Annotation的存在,对于面向接口的配置处理可以直接利用Annotation的属性完成控制,从而使得整体代码变得简洁.

Guess you like

Origin www.cnblogs.com/skykuqi/p/11445785.html