简介:
在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中的方法直接对参数进行控制。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)