繁体   English   中英

在Spring上下文中查找方法级自定义注释

[英]Find method level custom annotation in a Spring context

我想知道的是“ Spring bean中的所有类/方法都注释为@Versioned”。

我创建了自定义注释,

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Versioned {
    .....
}

当我使用Java反射来查找方法时,此注释非常有效

for(Method m: obj.getClass().getMethods()){
    if(m.isAnnotationPresent(Versioned.class)){
        .... // Do something
    }

但是当我访问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
                }
            }
        }
    }
}

实际上,此代码确实找到了其他注释,例如@RequestMapping。 我不确定自定义注释我做错了什么。

通过你的代码,我发现你正在使用Spring AOP和CGLIB Proxying。 由于您的类(具有使用@Versioned注释的方法)被代理。

我已经使用您的代码库测试了此解决方案。

使用以下代码,它应该可以解决您的问题。 在代码段下面查找更多选项:

@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
                }
            }
        }
    }
}

要检测代理类:

  • 对于使用任何代理机制的Spring AOP代理,请使用org.springframework.aop.support.AopUtils#isAoPProxy
  • 如果您使用Spring CGLIB代理(不是通过Spring AOP),请使用org.springframework.cglib.proxy.Proxy#isProxyClass
  • 如果您使用JDK代理进行代理,请使用java.lang.reflect.Proxy#isProxyClass

我刚才写一个if条件是你的情况充足; 但是如果使用多个代理实用程序, if-else必须根据上述信息编写多个if-else条件。

applicationContext.getBean(beanName).getClass()为您提供Spring在目标类周围创建的代理类。

你想要的是从你的Spring bean中获取目标类(如果有的话)。

Spring提供了一个很好的实用程序类来解析这个名为AopUtils.class的实用程序。

以下是如何使用它:

for(String beanName: applicationContext.getBeanDefinitionNames()){
    Method[] methods = AopUtils.getTargetClass(applicationContext.getBean(beanName)).getDeclaredMethods();

    for(Method m: methods){
        if(m.isAnnotationPresent(Versioned.class){
        }
    }
}

请注意,您必须导入spring-aop Maven依赖项才能获取AopUtils类:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
</dependency>
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?
                }

            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM