zoukankan      html  css  js  c++  java
  • 进阶Java编程(13)反射与Annotation

    1,反射取得Annotation信息

      从JDK1.5之后Java提供了Annotation技术支持,这种技术为项目的编写带来了新的模型,而后经过了十年的发展,Annotation的技术得到了非常广泛的应用,并且已经在所有的项目开发之中都会存在。

    获取Annotation信息

      在进行类或方法定义的时候都可以使用一系列的Annotation进行声明,如果要想获取这些Annotation的信息,那么就可以直接通过反射来完成。在java.lang.reflect里面有一个AccessibleObject类,在本类中提供有获取Annotation类的方法:

      ①获取全部Annotation:public Annotation[] getAnnotations()

      ②获取指定Annotation:public <T extends Annotation> T getAnnotation(Class<T> annotationClass)

      ·范例:定义一个接口,并且在接口上使用Annotation

     1 package com.mufasa.demo1;
     2 
     3 import java.lang.annotation.Annotation;
     4 import java.lang.reflect.Method;
     5 
     6 public class JavaAPIDemo {
     7     public static void main(String[] args) throws NoSuchMethodException {
     8         {//获取接口上的Annotation信息
     9             Annotation[] annotations=IMessage.class.getAnnotations();
    10             for(Annotation temp:annotations){
    11                 System.out.println(temp);
    12             }
    13         }
    14         System.out.println("-------");
    15         {//①获取MessageImpl子类上的Annotation,失败;②获取MessageImpl.toString方法
    16             Method method=MessageImpl.class.getDeclaredMethod("send", String.class);
    17             Annotation[] annotations=method.getAnnotations();
    18             for(Annotation temp:annotations){
    19                 System.out.println(temp);
    20             }
    21         }
    22     }
    23 }
     1 package com.mufasa.demo1;
     2 /*
     3 什么是函数式接口(Functional Interface)
     4 其实之前在讲Lambda表达式的时候提到过,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。
     5 这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。
     6 函数式接口用途
     7 它们主要用在Lambda表达式和方法引用(实际上也可认为是Lambda表达式)上。
     8  */
     9 @FunctionalInterface
    10 @Deprecated(since = "1.5")
    11 interface IMessage {//现在这里有两个Annotation
    12     public void send(String msg);
    13 }
     1 package com.mufasa.demo1;
     2 
     3 import java.io.Serializable;
     4 
     5 @SuppressWarnings("serial")//无法在程序执行的时候获取
     6 public class MessageImpl implements IMessage, Serializable {
     7     @Override
     8     public void send(String msg) {
     9         System.out.println("【消息发送】"+msg);
    10     }
    11 }

      不同的Annotation有它存在的范围,下面对比两个Annotation:

      现在发现【@FunctionalInterface】是在运行时生效的Annotation,所以当程序执行的时候可以获取此Annotation,而【@SuppressWarnings】是在源代码编写的时候有效。而在【RetentionPolicy】枚举类中还有一个class的定义,指的是类定义的时候生效。

    2,自定义Annotation

       现在已经清楚了Annotation的获取,以及Annotation的运行策略,但是最为关键性的一个因素是如何可以实现自定义的Annotation呢?为此在Java里面提供有新的语法,使用【@interface】来定义Annotation。

      ·范例:自定义Annotation

     1 package com.mufasa.demo2;
     2 
     3 import java.lang.annotation.Retention;
     4 import java.lang.annotation.RetentionPolicy;
     5 
     6 @Retention(RetentionPolicy.RUNTIME)//定义Annotation的运行策略
     7 @interface DefaultAnnotation {//自定义Annotation
     8     public String title();//获取数据
     9     public String url() default "www.cnblogs.com";//获取数据,默认值
    10 }
     1 package com.mufasa.demo2;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 
     6 public class JavaAPIDemo {
     7     public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
     8         Method method=Message.class.getMethod("send", String.class);//获取指定方法
     9         DefaultAnnotation annotation=method.getAnnotation(DefaultAnnotation.class);//获取指定Annotation
    10 //        System.out.println(annotation.title());
    11 //        System.out.println(annotation.url());
    12         String msg=annotation.title()+"("+annotation.url()+")";//消息内容
    13         method.invoke(Message.class.getDeclaredConstructor().newInstance(),msg);
    14     }
    15 }

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

    3,工厂设计模式与Annotation整合

       现在已经清楚Annotation的整体作用,但是Annotation在开发之中能做哪些事情呢?为了帮助大家进一步理解Annotation的处理目的下面将结合工厂设计模式来应用Annotation操作。

    1 package com.mufasa.demo3;
    2 
    3 import java.lang.annotation.Retention;
    4 import java.lang.annotation.RetentionPolicy;
    5 
    6 @Retention(RetentionPolicy.RUNTIME)
    7 public @interface UseMessage {
    8     public Class<?> clazz();
    9 }
     1 package com.mufasa.demo3;
     2 
     3 @UseMessage(clazz = MessageImpl.class)//!!!通过注解来控制整个程序的完成!!!
     4 public class MessageService {
     5     private IMessage message;
     6     public MessageService(){
     7         UseMessage useMessage=MessageService.class.getAnnotation(UseMessage.class);
     8         this.message=(IMessage) Factory.getInstance(useMessage.clazz());
     9     }
    10     public void send(String msg){
    11         this.message.send(msg);
    12     }
    13 }
     1 package com.mufasa.demo3;
     2 
     3 public class JavaAPIDemo {
     4     public static void main(String[] args){
     5         //①普通
     6 //        IMessage msg=Factory.getInstance(MessageImpl.class);
     7 //        msg.send("www.cnblogs.com");
     8         //②特殊
     9         MessageService messageService=new MessageService();
    10         messageService.send("www.cnblogs.com");
    11     }
    12 }
    13 /*
    14 【代理连接】进行消息发送通道的连接
    15 【消息发送】www.cnblogs.com
    16 【代理断开】关闭连接通道
    17  */
     1 package com.mufasa.demo3;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 
     5 class Factory {
     6     private Factory(){}
     7     public static <T> T getInstance(Class<T> clazz){//直接返回实例化操作对象
     8         try{
     9             return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance());
    10         }catch (Exception e){
    11             e.printStackTrace();
    12             return null;
    13         }
    14     }
    15 }

      由于Annotation的存在,所以对于面向接口的编程的配置处理将可以直接利用Annotation的属性完成控制,从而使得整体代码变得简洁。

  • 相关阅读:
    前后端分离的若依(ruoyi)基本使用
    Redis (error) NOAUTH Authentication required.解决方法
    Creating Server TCP listening socket 127.0.0.1:6379: bind: No error。。。启动遇到问题的解决办法
    持续集成
    Java compiler level does not match the version of the installed Java project facet问题解决
    控制台报错:Unknown database 'xxxxx'
    走进docker-machine
    走进docker-compose
    java新手学习路线
    Spring WebFlux 教程:如何构建反应式 Web 应用程序
  • 原文地址:https://www.cnblogs.com/Mufasa/p/11186113.html
Copyright © 2011-2022 走看看