随笔都是学习笔记
随笔仅供参考,为避免笔记中可能出现的错误误导他人,请勿转载。

简介:

在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中的方法直接对参数进行控制。

 

posted on 2022-03-09 16:02  时间完全不够用啊  阅读(1634)  评论(0编辑  收藏  举报