java:从spring-core移植的注解(annotation)扫描工具模组common-annotutils(适用JDK 1.7)

AnnotationUtils

spring-core的部件组装基本原理是基于注解(annotation),通过扫描类、方法、成员上定义的注解来决定组装逻辑。

spring-core将注解扫描框架封装为一个工具类:org.springframework.core.annotation.AnnotationUtils,使用这个工具类就可以从一个复杂类型或方法中获取指定的注解信息,大概就是这样:

java 复制代码
	AppConstantType annot = AnnotationUtils.findAnnotation(ClassB.class,AppConstantType.class);
	SyStem.out.printf("%s\n",annot);

这个注解扫描框架对于希望建立以注解组装机制的应用就很有用。但它是深度集成在spring-core代码中的。如果希望不依赖spring框架使用这个工具,只能自己想办法将org.springframework.core.annotation包下的代码抽取出来使用,而我的项目需要在JDK 1.7环境下使用,我现在现在使用的spring-core 5.x版本最低要求JDK 1.8。

所以org.springframework.core.annotation包下的代码大量使用了JDK 1.8的新特性:lamda表达、steam等。

所以对于我来说不仅要把org.springframework.core.annotation包下的代码抽取出来,还要对代码进行大量的重构,以适应JDK 1.7 版本。

花了差不多一周时间,总算完成了移植工作,为了验证代码重构的正确性,我同时还将org.springframework.core.annotation包对应的单元测试代码(spring-core/src/test/java/org/springframework/core/annotation)也同步移植出来。最终跑通了所有的单元测试。

common-annotutils

为了方便使用,我将移植出来的spring-core将注解扫描框架封装为jar包并发布到maven中央仓库。

依赖引用方式如下:

maven:

xml 复制代码
		<dependency>
			<groupId>com.gitee.l0km</groupId>
			<artifactId>common-annotutils</artifactId>
			<version>2.9.0</version>
		</dependency>

gradle:

implementation group: 'com.gitee.l0km', name: 'common-annotutils', version: '2.9.0'

调用示例

java 复制代码
import static org.junit.Assert.*;

import java.lang.reflect.Method;

import static net.gdface.utils.SimpleLog.log;

import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.gitee.l0km.common.annotations.AppConstantField;
import com.gitee.l0km.common.annotations.AppConstantType;
import com.gitee.l0km.common.annotations.CellLogTag;
import com.gitee.l0km.common.annotations.TestLogTag;
import com.google.common.collect.Multimap;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AnnotationTest {

	@Test
	public void test2AnnotationUtils() {
		try {
			{
				AppConstantType annot = AnnotationUtils.findAnnotation(ClassB.class,AppConstantType.class);
				log("{}",annot);
			}
			{
				AppConstantType annot = AnnotationUtils.findAnnotation(In2.class,AppConstantType.class);
				log("{}",annot);
			}
			{
				AppConstantField annot = AnnotationUtils.findAnnotation(ClassB.class.getMethod("m0"),AppConstantField.class);
				log("{}",annot);
			}
				
		} catch (Exception e) {
			e.printStackTrace();
			fail();
		}
	}
	@Test
	public void test3GetAnnotation() {
		try {
			{
				Method method = ClassB.class.getMethod("m0");
				TestLogTag annot = AnnotationUtils.findAnnotation(method,TestLogTag.class);
				log("{}",annot);
				CellLogTag cellLogTag= AnnotationUtils.getAnnotation(annot, CellLogTag.class);
				log("{}",cellLogTag);
			}
				
		} catch (Exception e) {
			e.printStackTrace();
			fail();
		}
	}
	@Test
	public void test4GetAllAnnotationAttributes() {
		try {
			{
				Method method = ClassA.class.getMethod("m0");
				Multimap<String, Object> attrs = AnnotatedElementUtils.getAllAnnotationAttributes(method,TestLogTag.class.getName());
				log("{}",attrs);
			}
			{
				Method method = ClassB.class.getMethod("m0");
				Multimap<String, Object> attrs = AnnotatedElementUtils.getAllAnnotationAttributes(method,TestLogTag.class.getName());
				log("{}",attrs);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			fail();
		}
	}
	@AppConstantType
	public static class ClassA {
		@AppConstantField
		@TestLogTag(TestEamLogTag.DT_ADD_LOG)
		public void m0() {};
	}
	public static class ClassB extends ClassA {
		@Override
		@TestLogTag(value=TestEamLogTag.DT_ADD_DEV,tag="hello")
		public void m0() {};
		
	}
	@AppConstantType
	public static interface In1{}
	public static interface In2 extends In1{}
	public static class ClassC implements In1{}

}

完整代码

完整代码参见码云仓库:
https://gitee.com/l0km/common-java/tree/master/common-annotutils

单元测试代码位置:
https://gitee.com/l0km/common-java/tree/master/common-annotutils-test

相关推荐
isolusion几秒前
Springboot的创建方式
java·spring boot·后端
zjw_rp29 分钟前
Spring-AOP
java·后端·spring·spring-aop
Oneforlove_twoforjob41 分钟前
【Java基础面试题033】Java泛型的作用是什么?
java·开发语言
TodoCoder1 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试
向宇it1 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
小蜗牛慢慢爬行1 小时前
Hibernate、JPA、Spring DATA JPA、Hibernate 代理和架构
java·架构·hibernate
星河梦瑾2 小时前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富2 小时前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想2 小时前
JMeter 使用详解
java·jmeter
言、雲2 小时前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库