Java反射类方法isAnnotationPresent(Class)无法判断代理类方法是否包含注解及解决方法

现象:当类的方法使用Spring事务注解@Transactional后,再使用isAnnotationPresent(Class)判断类方法是否包含注解时,会一直返回false,无法正确获取类方法注解。

测试代码

方法注解@JobHandler

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface JobHandler {
	String value();
}

类注解@JobWorker

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Component
public @interface JobWorker {
}
第一种情况:不使用Spring的事务注解@Transactional,可以正确的拿到方法的注解,测试类如下
@JobWorker
public class HelloAnnotation {
	
	@JobHandler("sayHello")
	public void sayHello() {
		System.out.println("hello annotation");
	}
	
//	@Transactional
	public void insert() {
		System.out.println("插入成功");
	}
}

测试方法

	@Test
	public void testIsAnnotationPresent() {
		Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobWorker.class);
		
		for (Object serviceBean : serviceBeanMap.values()) {
			System.out.println(">>>>>>>> 标记了@JobWorker注解的类" + serviceBean.getClass());
			Method[] methods = serviceBean.getClass().getDeclaredMethods();
			for (Method method : methods) {
				if (method.isAnnotationPresent(JobHandler.class)) {
					System.out.println(">>>>>>>> " + method.getName() + "包含注解@JobHandler");
				} else {
					System.out.println(">>>>>>>> " + method.getName() + "不包含注解@JobHandler");
				}
			}
		}
	}

测试结果:可以看到正确判断方法是否包含的注解,特别注意的是获取到标记了@JobWorker注解的类是class com.demo.mybatis.anno.HelloAnnotation

>>>>>>>> 标记了@JobWorker注解的类class com.demo.mybatis.anno.HelloAnnotation
>>>>>>>> insert不包含注解@JobHandler
>>>>>>>> sayHello包含注解@JobHandler
第二种情况:使用Spring的事务注解@Transactional,isAnnotationPresent(Class)就无法正确的拿到方法的注解了,测试类如下
@JobWorker
public class HelloAnnotation {
	
	@JobHandler("sayHello")
	public void sayHello() {
		System.out.println("hello annotation");
	}
	
	@Transactional
	public void insert() {
		System.out.println("插入成功");
	}
}

测试结果,可以看到HelloAnnotation类被Spring生成的代理类包含了。造成了无法正确获得方法注解。原因是这个类在事务管理时,被当成了类代理。根据class反射拿到的是代理类,所以拿不到对应的注解。

>>>>>>>> 标记了@JobWorker注解的类class com.demo.mybatis.anno.HelloAnnotation$$EnhancerBySpringCGLIB$$718f198e
>>>>>>>> insert不包含注解@JobHandler
>>>>>>>> sayHello不包含注解@JobHandler
>>>>>>>> CGLIB$sayHello$1不包含注解@JobHandler
>>>>>>>> CGLIB$insert$0不包含注解@JobHandler

总结:使用了Spring的事务注解@Transactional后,原目标类被当成了类代理。根据class反射拿到的是代理类,代理类的方法不包含方法注解,所以拿不到对应的注解。

使用了Spring的事务注解@Transactional后,获取原类注解的方法

直接获取代理类的父亲即可,因为代理类是继承原类的,获取方法如下

@Test
public void testIsAnnotationPresent() {
	Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobWorker.class);
	for (Object serviceBean : serviceBeanMap.values()) {
		// 直接获取代理类的父类getSuperclass()
		System.out.println(">>>>>>>> 代理类,标记了@JobWorker注解的类" + serviceBean.getClass().getSuperclass());
		Method[] methods = serviceBean.getClass().getSuperclass().getDeclaredMethods();
		for (Method method : methods) {
			if (method.isAnnotationPresent(JobHandler.class)) {
				System.out.println(">>>>>>>> " + method.getName() + "包含注解@JobHandler");
			} else {
				System.out.println(">>>>>>>> " + method.getName() + "不包含注解@JobHandler");
			}
		}
	}
}

测试结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值