java 在 Spring 上下文中查找方法级别的自定义注释
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27929965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find method level custom annotation in a Spring context
提问by kamoor
All I wanted to find out was "all the class/methods in Springbeans which are annotated as @Versioned".
我只想找出“ Springbean 中所有被注释为@Versioned的类/方法”。
I created my custom annotation as,
我创建了我的自定义注释,
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Versioned {
.....
}
This annotation works perfectlywhen I use Java reflection to find methods as:
当我使用 Java 反射来查找方法时,此注释非常有效:
for(Method m: obj.getClass().getMethods()){
if(m.isAnnotationPresent(Versioned.class)){
.... // Do something
}
But it does not work when I access Spring beans and try similar check:
但是当我访问 Spring bean 并尝试类似的检查时它不起作用:
public class VersionScanner implements ApplicationContextAware{
public void setApplicationContext(ApplicationContext applicationContext){
for(String beanName: applicationContext.getBeanDefinitionNames()){
for(Method m: applicationContext.getBean(beanName).getClass().getDeclaredMethods()){
if(m.isAnnotationPresent(Versioned.class){
// This is not WORKING as expected for any beans with method annotated
}
}
}
}
}
In fact, this code does find other annotations such as @RequestMapping. I am not sure what I am doing wrong with my custom annotation.
事实上,这段代码确实找到了其他注解,例如@RequestMapping。我不确定我的自定义注释做错了什么。
回答by owaism
Going through your code, I figured out that you are using Spring AOP with CGLIB Proxying. Due to which your classes (which have methods annotated with @Versioned) are being proxied.
通过您的代码,我发现您正在使用带有 CGLIB 代理的 Spring AOP。因此,您的类(具有用 注释的方法@Versioned)被代理。
I have tested this solution with your code base.
我已经用你的代码库测试了这个解决方案。
Use the following code, and it should resolve your issue. Look for more options below the code snippet:
使用以下代码,它应该可以解决您的问题。在代码片段下方寻找更多选项:
@Configuration
public class VersionScanner implements ApplicationContextAware {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Object obj = applicationContext.getBean(beanName);
/*
* As you are using AOP check for AOP proxying. If you are proxying with Spring CGLIB (not via Spring AOP)
* Use org.springframework.cglib.proxy.Proxy#isProxyClass to detect proxy If you are proxying using JDK
* Proxy use java.lang.reflect.Proxy#isProxyClass
*/
Class<?> objClz = obj.getClass();
if (org.springframework.aop.support.AopUtils.isAopProxy(obj)) {
objClz = org.springframework.aop.support.AopUtils.getTargetClass(obj);
}
for (Method m : objClz.getDeclaredMethods()) {
if (m.isAnnotationPresent(Versioned.class)) {
//Should give you expected results
}
}
}
}
}
To detect a proxy class:
检测代理类:
- For Spring AOP proxy using any proxying mechanism use
org.springframework.aop.support.AopUtils#isAoPProxy - If you are proxying with Spring CGLIB (not via Spring AOP), use
org.springframework.cglib.proxy.Proxy#isProxyClass - If you are proxying using JDK Proxy, use
java.lang.reflect.Proxy#isProxyClass
- 对于使用任何代理机制的 Spring AOP 代理,请使用
org.springframework.aop.support.AopUtils#isAoPProxy - 如果您使用 Spring CGLIB(不是通过 Spring AOP)进行代理,请使用
org.springframework.cglib.proxy.Proxy#isProxyClass - 如果您使用 JDK 代理进行代理,请使用
java.lang.reflect.Proxy#isProxyClass
I have just written one ifcondition which is sufficient in your case; but in case multiple proxying utilities are used, multiple if-elseconditions will have to be written based on the information above.
我刚刚写了一个if条件,对你的情况来说是充分的;但如果使用多个代理实用程序,if-else则必须根据上述信息编写多个条件。
回答by Angad
applicationContext.getBean(beanName).getClass()gives you the proxied class that Spring creates around your target class.
applicationContext.getBean(beanName).getClass()为您提供 Spring 在您的目标类周围创建的代理类。
What you want is to get hold of the target class, if any, from your Spring bean.
您想要的是从 Spring bean 中获取目标类(如果有)。
Spring provides a nice utility class for resolving this called AopUtils.class.
Spring 提供了一个很好的实用程序类来解决这个问题,称为 AopUtils.class。
Below is how you would use it:
以下是您将如何使用它:
for(String beanName: applicationContext.getBeanDefinitionNames()){
Method[] methods = AopUtils.getTargetClass(applicationContext.getBean(beanName)).getDeclaredMethods();
for(Method m: methods){
if(m.isAnnotationPresent(Versioned.class){
}
}
}
Note that you will have to import the spring-aopMavendependency to get hold of the AopUtils class:
请注意,您必须导入spring-aopMaven依赖项才能获取 AopUtils 类:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
回答by AH-64
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Object obj = applicationContext.getBean(beanName);
Class<?> objClz = obj.getClass();
if (org.springframework.aop.support.AopUtils.isAopProxy(obj)) {
objClz = org.springframework.aop.support.AopUtils.getTargetClass(obj);
}
for (Method m : objClz.getDeclaredMethods()) {
if (m.isAnnotationPresent(Transactional.class)) {
Transactional transactional = m.getAnnotation(Transactional.class);
Class<? extends Throwable>[] value = transactional.rollbackFor();
if (value == null){
// help !!!
// If value is null, I want to set a value for him like Exception.class How can I modify it?
}
}
}
}
}

