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反射拿到的是代理類,代理類的方法不包含方法註解,所以拿不到對應的註解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章