57-反射与Annotation

本文介绍了Java反射机制和注解的使用方法,包括如何通过反射获取注解信息、定义注解及其实现自定义注解的过程。同时展示了注解与工厂设计模式整合的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射与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);

6Y2YGV.png

定义一个接口,并且使用Annotation

package cn.mldn.demo;

import java.io.Serializable;
import java.lang.annotation.*;
import java.lang.reflect.Method;

public class reflect_Annotation {
	public static void main(String[] args) throws Exception{
		{		//获取接口的Annotation信息 
			Annotation annotation[] = IMessage.class.getAnnotations();		//获取全部Annotation
			for(Annotation temp: annotation) {
				System.out.println(temp);
			}
		}
		System.out.println("***********************************");
		{		//获取子类的Annotation信息 
			Annotation annotation[] = MessageImpl.class.getAnnotations();		//获取全部Annotation
			for(Annotation temp: annotation) {
				System.out.println(temp);
			}
		}
		System.out.println("***********************************");
		{		//获取子类.toString()方法的Annotation信息 
			Method methods = MessageImpl.class.getDeclaredMethod("send", String.class);
			Annotation annotation[] = methods.getAnnotations();		//获取全部Annotation
			for(Annotation temp: annotation) {
				System.out.println(temp);
			}
		}
	}
}

@FunctionalInterface
@Deprecated(since="1.0")
interface IMessage{		//有两个Annotation
	public void send(String msg);
}

@SuppressWarnings("serial")		//这个Annotation无法在程序执行时获取
class MessageImpl implements IMessage,Serializable{
	@Override		//这个Annotation无法在程序执行时获取
	public void send(String msg) {
		System.out.println("[消息发送]" + msg);
	}
}

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

@FunctionalInterface(运行时生效)@SuppressWarnings(源代码生效)
@Doucment @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FunctionalInterface{}@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,MODULE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings{}

  运行时生效是在程序运行时生效的Annotation,而另外一个则为源代码编写时有效。而RentationPolice枚举类中还有一个Class定义,指的是在类定义的时候生效。

自定义Annotation

  最为关键性的是实现自定义的Annotation,为此Java中提供新的语法,使用“@interface”来定义Annotation。

自定义Annotation

package cn.mldn.demo;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

public class reflect_Annotation {

	public static void main(String[] args) throws Exception{
		Method method = MessageT.class.getMethod("send", String.class);
		DefaultAnnotation annotation = method.getAnnotation(DefaultAnnotation.class);		//获取指定Annotation
		System.out.println(annotation.title());		//调用annotation中的方法
		System.out.println(annotation.url());
		String msg = annotation.title() + "-" + annotation.url();
		method.invoke(MessageT.class.getDeclaredConstructor().newInstance(), msg);
	}
}

class MessageT{
	@DefaultAnnotation(title = "test")
	public void send(String msg) {
		System.out.println("[message send]" + msg);
	}
}

@Retention(RetentionPolicy.RUNTIME)		//定义Annotation策略
@interface DefaultAnnotation{		//自定义Annotation
	public String title();		//获取数据
	public String url() default "www.baidu.com";		//获取数据,默认值
}

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

工厂设计模式与Annotation整合

  为了进一步了解Annotation在开发中处理的目的,结合工厂设计模式应用Annotation操作。
工厂、代理以及Annotation相结合

package cn.mldn.demo;

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 reflect_Annotation {
	public static void main(String[] args) throws Exception{
		MessageService messageService = new  MessageService();
		messageService.send("www.baidu.com");
	}
}

@Retention(RetentionPolicy.RUNTIME)
@interface UseMessage{
	public Class<?> clazz();
}

@UseMessage(clazz = NetMessageImpl.class)
class MessageService{
	private IMessage message;
	public MessageService() {
		UseMessage use = MessageService.class.getAnnotation(UseMessage.class);
		this.message = (IMessage)Factory.getInstance(use.clazz());		//直接通过Annotation获取,使用Annotation实现类的使用
	}
	public void send(String msg) {
		this.message.send(msg);
	}
}

class Factory{
	private Factory() {}
	public static <T> T getInstance(Class<T> clazz) {		//直接返回一个实例化对象
		try {
			return (T) new MessageProxyz().bind(clazz.getDeclaredConstructor().newInstance());
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}

interface IMessage{
	public void send(String msg);
}

class MessageImpl implements IMessage{
	@Override
	public void send(String msg) {
		System.out.println("[Message send]" + msg);
	}
}

class NetMessageImpl implements IMessage{
	@Override
	public void send(String msg) {
		System.out.println("[NetMessage send]" + msg);
	}
}

class MessageProxyz implements InvocationHandler{
	private Object target;
	public Object bind(Object target) {
		this.target = target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
	public boolean connect() {
		System.out.println("[Proxy]消息通道建立");
		return true;
	}
	public void close() {
		System.out.println("[Proxy]消息通道关闭");
	}
	@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的存在,所以面向接口的编程配置处理可以直接利用Annotation的属性进行控制,从而使得整体代码变得简洁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值