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反射拿到的是代理类,代理类的方法不包含方法注解,所以拿不到对应的注解。

你可能感兴趣的:(java)