java word批注_使用反射处理Java批注

本文介绍如何使用Java反射API处理自定义注解,包括DoItLikeThis、DoItLikeThat和DoItWithAWhiffleBallBat注解。通过示例代码展示了如何检查和处理这些注解。

java word批注

在上一篇有关Java注释的文章中,我概述了一个最近的用例,并为您提供了一些自定义注释的示例以及如何使用它们。

在本文中,我将更进一步,并为您提供一些自定义注释的示例,以及如何使用Java Reflection API处理这些自定义注释。 学习完本教程后,您应该对自定义注释可以提供的简单性和灵活性有了更好的了解。 因此,让我们深入研究代码!

自定义注释清单

我今天为示例代码创建了三个不同的注释,分别是DoItLikeThisDoItLikeThatDoItWithAWhiffleBallBat注释。 每个注释针对的是不同的元素类型,并且具有略微不同的属性,因此我可以向您展示如何查找和处理它们。

喜欢这个注释

DoItLikeThis注释针对ElementType TYPE,这使其仅可用于Java类型。 该批注具有三个可选元素description,action和一个布尔字段shouldDoItLikeThis。 如果在使用此注释时未为这些元素提供任何值,则它们将默认为指定的值。

package com.keyhole.jonny.blog.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation created for doing it like this.
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoItLikeThis {

	/**
	 * @return - The description.
	 */
	String description() default "";

	/**
	 * @return - The action.
	 */
	String action() default "";

	/**
	 * @return - Should we be doing it like this.
	 */
	boolean shouldDoItLikeThis() default false;

}

像注释一样

DoItLikeThat注释是仅针对Java字段的注释。 此批注还具有一个类似的布尔元素,名称为ShouldDoItLikeThat,它没有指定默认值,因此在使用批注时是必需的元素。 批注还包含一个定义为String数组的元素,该元素将包含应检查的用户角色列表。

package com.keyhole.jonny.blog.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation created for doing it like that
 * instead of like this.
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoItLikeThat {

	/**
	 * @return - Should we be doing it like that.
	 */
	boolean shouldDoItLikeThat();

	/**
	 * @return - List of user roles that can do it like that.
	 */
	String[] roles() default{};

}

DoWWithAWhiffleBallBat批注

DoItWithAWhiffleBallBat注释旨在仅与方法一起使用,并且与其他注释类似。 它也有一个类似的布尔元素,这个名字叫做shouldDoItWithAWhiffleBallBat。 还定义了另一个元素,该元素使用WhiffleBallBat枚举定义了可用的不同类型的Whiffle Ball bat,默认为经典的黄色经典Whiffle Ball bat。

package com.keyhole.jonny.blog.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * When you can't do it like this or do it like that,
 * do it with a whiffle ball bat.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoItWithAWhiffleBallBat {

	/**
	 * @return - Should we be doing it with a whiffle ball bat.
	 */
	boolean shouldDoItWithAWhiffleBallBat() default false;

	/**
	 * @return - Sweet, which type of whiffle ball bat?
	 */
	WhiffleBallBat batType() default WhiffleBallBat.YELLOW_PLASTIC;

}

带注释的类

现在我们已经为示例定义了注释,我们需要几个类进行注释。 每个类都提供了使用指定元素以及依赖默认值的注释的示例用法。 还包括其他未注释的字段和方法,因此注释处理器不应对其进行处理。 这是两个示例类的源代码:

带注释的一类

package com.keyhole.jonny.blog.annotations;

import java.util.Date;

@DoItLikeThis
public class AnnotatedOne implements AnnotatedClass {

	@DoItLikeThat(shouldDoItLikeThat = false)
	private String field1;

	@DoItLikeThat(shouldDoItLikeThat = true, roles = { "admin", "root" })
	private String field2;

	private String field3;
	private Date dateDoneLikeThis;

	/* setters and getters removed for brevity */

	@DoItWithAWhiffleBallBat(batType = WhiffleBallBat.BLACK_PLASTIC, shouldDoItWithAWhiffleBallBat = true)
	public void doWhateverItIs() {
		// method implementation
	}

	public void verifyIt() {
		// method implementation
	}

}

带注释的二级

package com.keyhole.jonny.blog.annotations;

import java.util.Date;

@DoItLikeThis(action = "PROCESS", shouldDoItLikeThis = true, description = "Class used for annotation example.")
public class AnnotatedTwo implements AnnotatedClass {

	@DoItLikeThat(shouldDoItLikeThat = true)
	private String field1;

	@DoItLikeThat(shouldDoItLikeThat = true, roles = { "web", "client" })
	private String field2;

	private String field3;
	private Date dateDoneLikeThis;

	/* setters and getters removed for brevity */

	@DoItWithAWhiffleBallBat(shouldDoItWithAWhiffleBallBat = true)
	public void doWhateverItIs() {
		// method implementation
	}

	public void verifyIt() {
		// method implementation
	}

}

处理注释

使用反射来处理注释实际上非常简单。 对于您可以为其创建和应用注释的每种元素类型,这些元素上都有一些使用注释的方法。 您需要做的第一件事是检查元素以确定是否有任何注释,或检查该元素是否存在特定注释。

每个元素类型Class,Field和Method都实现了AnnotatedElement接口,该接口定义了以下方法:

  • getAnnotations() –返回此元素上存在的所有注释,包括所有继承的注释。
  • getDeclaredAnnotations() –仅返回直接存在于此元素上的注释。
  • getAnnotation(Class <A>注记类) –返回指定注解类型的元素注解,如果找不到,则返回null。
  • isAnnotation() –如果要检查的元素是注释,则返回true。
  • isAnnotationPresent(Class <?Extends Annotation>注解类) –如果所检查的元素上存在指定的注解,则返回true。

在处理批注时,我们要做的第一件事是检查批注是否存在。 为此,我们将对批注处理进行以下检查:

if (ac.getClass().isAnnotationPresent(DoItLikeThis.class)) {
		// process the annotation, "ac" being the instance of the object we are inspecting

	}

找到所需的批注后,我们将获取该批注并为该批注进行任何处理。 至此,我们将可以访问注释的元素及其值。 请注意,没有任何用于访问注释元素的获取器或设置器。

DoItLikeThis anno = ac.getClass().getAnnotation(DoItLikeThis.class);
	System.out.println("Action: " + anno.action());
	System.out.println("Description: " + anno.description());
	System.out.println("DoItLikeThis:" + anno.shouldDoItLikeThis());

对于字段和方法,检查当前注释会略有不同。 对于这些类型的元素,我们需要遍历所有字段或方法以确定元素上是否存在注释。 您将需要从Class中获取所有字段或方法,遍历Field或Method数组,然后确定元素上是否存在注释。 看起来应该像这样:

Field[] fields = ac.getClass().getDeclaredFields();
	for (Field field : fields) {
		if (field.isAnnotationPresent(DoItLikeThat.class)) {
			DoItLikeThat fAnno = field.getAnnotation(DoItLikeThat.class);
			System.out.println("Field: " + field.getName());
			System.out.println("DoItLikeThat:" + fAnno.shouldDoItLikeThat());
			for (String role : fAnno.roles()) {
				System.out.println("Role: " + role);
			}
		}
	}

结论

如您所见,创建自己的注释并对其进行处理非常简单。 在我提供的示例中,我们只是将元素的值输出到控制台或日志。 希望您能看到这些的潜在用途,并且将来可能会真正考虑创建自己的。 我在注释中看到的一些最佳用法是它们替换一些配置代码或经常使用的通用代码,例如验证字段的值或将业务对象映射到Web表单。

最后,这是完整的源代码以及用于执行代码的简单Java主类:

带注释的类处理器

package com.keyhole.jonny.blog.annotations;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class AnnotatedClassProcessor {

	public void processClass(AnnotatedClass ac) {
		System.out.println("------Class Processing Begin---------");

		System.out.println("Class: " + ac.getClass().getName());
		if (ac.getClass().isAnnotationPresent(DoItLikeThis.class)) {
			// process the annotation, "ac" being the instance of the object we are inspecting
			DoItLikeThis anno = ac.getClass().getAnnotation(DoItLikeThis.class);
			System.out.println("Action: " + anno.action());
			System.out.println("Description: " + anno.description());
			System.out.println("DoItLikeThis:" + anno.shouldDoItLikeThis());

			System.out.println("------Field Processing---------");
			Field[] fields = ac.getClass().getDeclaredFields();
			for (Field field : fields) {
				if (field.isAnnotationPresent(DoItLikeThat.class)) {
					DoItLikeThat fAnno = field.getAnnotation(DoItLikeThat.class);
					System.out.println("Field: " + field.getName());
					System.out.println("DoItLikeThat:" + fAnno.shouldDoItLikeThat());
					for (String role : fAnno.roles()) {
						System.out.println("Role: " + role);
					}
				}
			}

			System.out.println("------Method Processing---------");
			Method[] methods = ac.getClass().getMethods();
			for (Method method : methods) {
				if ( method.isAnnotationPresent(DoItWithAWhiffleBallBat.class)) {
					DoItWithAWhiffleBallBat mAnno = method.getAnnotation(DoItWithAWhiffleBallBat.class);
					System.out.println("Use WhiffleBallBat? " + mAnno.shouldDoItWithAWhiffleBallBat());
					System.out.println("Which WhiffleBallBat? " + mAnno.batType());
				}
			}

		}
		System.out.println("------Class Processing End---------");
	}
}

运行处理器

package com.keyhole.jonny.blog.annotations;

public class RunProcessor {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		AnnotatedClassProcessor processor = new AnnotatedClassProcessor();
		processor.processClass(new AnnotatedOne());
		processor.processClass(new AnnotatedTwo());

	}

}

翻译自: https://www.javacodegeeks.com/2014/09/processing-java-annotations-using-reflection.html

java word批注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值