Find method level custom annotation in a Spring context

前端 未结 3 1650
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-05 14:03

All I wanted to find out was \"all the class/methods in Spring beans which are annotated as @Versioned\".

I created my custom annotation as,

@Target({Ele         


        
相关标签:
3条回答
  • 2021-02-05 14:14

    applicationContext.getBean(beanName).getClass() gives you the proxied class that Spring creates around your target class.

    What you want is to get hold of the target class, if any, from your Spring bean.

    Spring provides a nice utility class for resolving this called 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-aop Maven dependency to get hold of the AopUtils class:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring.version}</version>
    </dependency>
    
    0 讨论(0)
  • 2021-02-05 14:16

    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.

    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

    I have just written one if condition which is sufficient in your case; but in case multiple proxying utilities are used, multiple if-else conditions will have to be written based on the information above.

    0 讨论(0)
  • 2021-02-05 14:19
    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?
                    }
    
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题