zoukankan      html  css  js  c++  java
  • 【Java】关于获取注解的问题发现

    同事设置了个注解,想用Spring获取的Bean来找到Class获取注解

    但是发现是空的,在查看的Spring返回Bean之后,发现这个Bean对象并不是原生的实例

    而是被Spring代理增强的代理对象

    为了复现这个问题,这里我写了个样例:

    首先有两个样例注解(一个叫A 一个叫B,B也是一样的就不写了):

    package cn.cloud9.test.reflect.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AnnoA {
        String value() default "";
    }

    再写一个A类,里面就是一个方法没别的

    打上A和B注解

    package cn.cloud9.test.reflect.sample;
    
    import cn.cloud9.test.reflect.annotation.AnnoA;
    import cn.cloud9.test.reflect.annotation.AnnoB;
    
    @AnnoA
    @AnnoB
    public class A {
    
        public void fun() {
            System.out.println("A.fun executed... ");
        }
    }

    为了模拟Spring代理的场景,这里要引入CGLIB组件

            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2.2</version>
            </dependency>

    编写样例代码:

    package cn.cloud9.test.reflect;
    
    import cn.cloud9.test.reflect.sample.A;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import org.junit.Test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    public class ReflectAndAnnotation {
    
    
        @Test
        public void simpleGet() throws Exception {
    
            Class<?> aClass = Class.forName("cn.cloud9.test.reflect.sample.A");
    
            Annotation[] annotations = aClass.getAnnotations();
    
            Class<?> superclass = aClass.getSuperclass();
            System.out.println(superclass);
    
            for (Annotation annotation : annotations) {
                System.out.println(annotation.toString());
            }
        }
    
    }

    执行之后,自然而然的就能得到我们设置的注解:

    "C:Program FilesJavajdk1.8.0_301injava.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2libidea_rt.jar=57548:C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2libidea_rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2pluginsjunitlibjunit5-rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2pluginsjunitlibjunit-rt.jar;C:Program FilesJavajdk1.8.0_301jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_301jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_301jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_301jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_301jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_301jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_301jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_301jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_301jrelibext
    ashorn.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_301jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_301jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_301jrelibjce.jar;C:Program FilesJavajdk1.8.0_301jrelibjfr.jar;C:Program FilesJavajdk1.8.0_301jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_301jrelibjsse.jar;C:Program FilesJavajdk1.8.0_301jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_301jrelibplugin.jar;C:Program FilesJavajdk1.8.0_301jrelib
    esources.jar;C:Program FilesJavajdk1.8.0_301jrelib
    t.jar;C:UsersCloud9IdeaProjectsEveryThing-Framework	arget	est-classes;C:UsersCloud9IdeaProjectsEveryThing-Framework	argetclasses;D:Maven Local Repositoryorgapachecuratorcurator-framework5.2.0curator-framework-5.2.0.jar;D:Maven Local Repositoryorgapachecuratorcurator-client5.2.0curator-client-5.2.0.jar;D:Maven Local Repositoryorgapachezookeeperzookeeper3.6.3zookeeper-3.6.3.jar;D:Maven Local Repositoryorgapachezookeeperzookeeper-jute3.6.3zookeeper-jute-3.6.3.jar;D:Maven Local Repositoryorgapacheyetusaudience-annotations.5.0audience-annotations-0.5.0.jar;D:Maven Local Repositoryio
    etty
    etty-handler4.1.63.Final
    etty-handler-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-common4.1.63.Final
    etty-common-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-resolver4.1.63.Final
    etty-resolver-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-buffer4.1.63.Final
    etty-buffer-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-transport4.1.63.Final
    etty-transport-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-codec4.1.63.Final
    etty-codec-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-transport-native-epoll4.1.63.Final
    etty-transport-native-epoll-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-transport-native-unix-common4.1.63.Final
    etty-transport-native-unix-common-4.1.63.Final.jar;D:Maven Local Repositoryorgapachecuratorcurator-recipes5.2.0curator-recipes-5.2.0.jar;D:Maven Local Repositorycommons-iocommons-io2.11.0commons-io-2.11.0.jar;D:Maven Local Repositorycommons-beanutilscommons-beanutils1.7.0commons-beanutils-1.7.0.jar;D:Maven Local Repositorycommons-loggingcommons-logging1.0.3commons-logging-1.0.3.jar;D:Maven Local Repositoryorgjavassistjavassist3.26.0-GAjavassist-3.26.0-GA.jar;D:Maven Local Repositorycomalibabafastjson1.2.78fastjson-1.2.78.jar;D:Maven Local Repositoryjavaxservletjavax.servlet-api4.0.1javax.servlet-api-4.0.1.jar;D:Maven Local Repositoryjavaxservletjstl1.2jstl-1.2.jar;D:Maven Local Repositoryjavaxservletjspjavax.servlet.jsp-api2.3.3javax.servlet.jsp-api-2.3.3.jar;D:Maven Local Repositoryorg
    eflections
    eflections.9.11
    eflections-0.9.11.jar;D:Maven Local Repositorycomgoogleguavaguava20.0guava-20.0.jar;D:Maven Local Repositorymysqlmysql-connector-java8.0.25mysql-connector-java-8.0.25.jar;D:Maven Local Repositorycomgoogleprotobufprotobuf-java3.11.4protobuf-java-3.11.4.jar;D:Maven Local Repositoryiojsonwebtokenjjwt.9.1jjwt-0.9.1.jar;D:Maven Local Repositorycomfasterxmljacksoncorejackson-databind2.9.6jackson-databind-2.9.6.jar;D:Maven Local Repositorycomfasterxmljacksoncorejackson-annotations2.9.0jackson-annotations-2.9.0.jar;D:Maven Local Repositorycomfasterxmljacksoncorejackson-core2.9.6jackson-core-2.9.6.jar;D:Maven Local Repositoryorgapachehttpcomponentshttpclient4.5.13httpclient-4.5.13.jar;D:Maven Local Repositoryorgapachehttpcomponentshttpcore4.4.13httpcore-4.4.13.jar;D:Maven Local Repositorycommons-codeccommons-codec1.11commons-codec-1.11.jar;D:Maven Local Repositoryorgapachehttpcomponentshttpmime4.5.13httpmime-4.5.13.jar;D:Maven Local Repositoryjunitjunit4.12junit-4.12.jar;D:Maven Local Repositoryorghamcresthamcrest-core1.3hamcrest-core-1.3.jar;D:Maven Local Repositoryorgslf4jslf4j-api1.7.32slf4j-api-1.7.32.jar;D:Maven Local Repositoryorgslf4jslf4j-log4j121.7.32slf4j-log4j12-1.7.32.jar;D:Maven Local Repositorylog4jlog4j1.2.17log4j-1.2.17.jar;D:Maven Local Repositorycglibcglib2.2.2cglib-2.2.2.jar;D:Maven Local Repositoryasmasm3.3.1asm-3.3.1.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 cn.cloud9.test.reflect.ReflectAndAnnotation,simpleGet
    class java.lang.Object
    @cn.cloud9.test.reflect.annotation.AnnoA(value=)
    @cn.cloud9.test.reflect.annotation.AnnoB(value=)
    
    Process finished with exit code 0

    那么在调用CGLIB的增强代理之后:

    package cn.cloud9.test.reflect;
    
    import cn.cloud9.test.reflect.sample.A;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import org.junit.Test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    public class ReflectAndAnnotation {
    
    
        @Test
        public void simpleGet() throws Exception {
    
            Class<?> aClass = Class.forName("cn.cloud9.test.reflect.sample.A");
    
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(aClass);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    System.out.println("before method run...");
                    Object result = proxy.invokeSuper(obj, args);
                    System.out.println("after method run...");
                    return result;
                }
            });
            A proxyA = (A) enhancer.create();
            proxyA.fun();
    
            Class<? extends A> proxyAClass = proxyA.getClass();
    
            System.out.println(proxyAClass);
    
            for (Annotation annotation : proxyAClass.getAnnotations()) {
                System.out.println(annotation);
            }
    
        }
    
    }

    执行发现,我们注解获取不到了

    "C:Program FilesJavajdk1.8.0_301injava.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2libidea_rt.jar=57581:C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2libidea_rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2pluginsjunitlibjunit5-rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2021.2.2pluginsjunitlibjunit-rt.jar;C:Program FilesJavajdk1.8.0_301jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_301jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_301jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_301jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_301jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_301jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_301jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_301jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_301jrelibext
    ashorn.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_301jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_301jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_301jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_301jrelibjce.jar;C:Program FilesJavajdk1.8.0_301jrelibjfr.jar;C:Program FilesJavajdk1.8.0_301jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_301jrelibjsse.jar;C:Program FilesJavajdk1.8.0_301jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_301jrelibplugin.jar;C:Program FilesJavajdk1.8.0_301jrelib
    esources.jar;C:Program FilesJavajdk1.8.0_301jrelib
    t.jar;C:UsersCloud9IdeaProjectsEveryThing-Framework	arget	est-classes;C:UsersCloud9IdeaProjectsEveryThing-Framework	argetclasses;D:Maven Local Repositoryorgapachecuratorcurator-framework5.2.0curator-framework-5.2.0.jar;D:Maven Local Repositoryorgapachecuratorcurator-client5.2.0curator-client-5.2.0.jar;D:Maven Local Repositoryorgapachezookeeperzookeeper3.6.3zookeeper-3.6.3.jar;D:Maven Local Repositoryorgapachezookeeperzookeeper-jute3.6.3zookeeper-jute-3.6.3.jar;D:Maven Local Repositoryorgapacheyetusaudience-annotations.5.0audience-annotations-0.5.0.jar;D:Maven Local Repositoryio
    etty
    etty-handler4.1.63.Final
    etty-handler-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-common4.1.63.Final
    etty-common-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-resolver4.1.63.Final
    etty-resolver-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-buffer4.1.63.Final
    etty-buffer-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-transport4.1.63.Final
    etty-transport-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-codec4.1.63.Final
    etty-codec-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-transport-native-epoll4.1.63.Final
    etty-transport-native-epoll-4.1.63.Final.jar;D:Maven Local Repositoryio
    etty
    etty-transport-native-unix-common4.1.63.Final
    etty-transport-native-unix-common-4.1.63.Final.jar;D:Maven Local Repositoryorgapachecuratorcurator-recipes5.2.0curator-recipes-5.2.0.jar;D:Maven Local Repositorycommons-iocommons-io2.11.0commons-io-2.11.0.jar;D:Maven Local Repositorycommons-beanutilscommons-beanutils1.7.0commons-beanutils-1.7.0.jar;D:Maven Local Repositorycommons-loggingcommons-logging1.0.3commons-logging-1.0.3.jar;D:Maven Local Repositoryorgjavassistjavassist3.26.0-GAjavassist-3.26.0-GA.jar;D:Maven Local Repositorycomalibabafastjson1.2.78fastjson-1.2.78.jar;D:Maven Local Repositoryjavaxservletjavax.servlet-api4.0.1javax.servlet-api-4.0.1.jar;D:Maven Local Repositoryjavaxservletjstl1.2jstl-1.2.jar;D:Maven Local Repositoryjavaxservletjspjavax.servlet.jsp-api2.3.3javax.servlet.jsp-api-2.3.3.jar;D:Maven Local Repositoryorg
    eflections
    eflections.9.11
    eflections-0.9.11.jar;D:Maven Local Repositorycomgoogleguavaguava20.0guava-20.0.jar;D:Maven Local Repositorymysqlmysql-connector-java8.0.25mysql-connector-java-8.0.25.jar;D:Maven Local Repositorycomgoogleprotobufprotobuf-java3.11.4protobuf-java-3.11.4.jar;D:Maven Local Repositoryiojsonwebtokenjjwt.9.1jjwt-0.9.1.jar;D:Maven Local Repositorycomfasterxmljacksoncorejackson-databind2.9.6jackson-databind-2.9.6.jar;D:Maven Local Repositorycomfasterxmljacksoncorejackson-annotations2.9.0jackson-annotations-2.9.0.jar;D:Maven Local Repositorycomfasterxmljacksoncorejackson-core2.9.6jackson-core-2.9.6.jar;D:Maven Local Repositoryorgapachehttpcomponentshttpclient4.5.13httpclient-4.5.13.jar;D:Maven Local Repositoryorgapachehttpcomponentshttpcore4.4.13httpcore-4.4.13.jar;D:Maven Local Repositorycommons-codeccommons-codec1.11commons-codec-1.11.jar;D:Maven Local Repositoryorgapachehttpcomponentshttpmime4.5.13httpmime-4.5.13.jar;D:Maven Local Repositoryjunitjunit4.12junit-4.12.jar;D:Maven Local Repositoryorghamcresthamcrest-core1.3hamcrest-core-1.3.jar;D:Maven Local Repositoryorgslf4jslf4j-api1.7.32slf4j-api-1.7.32.jar;D:Maven Local Repositoryorgslf4jslf4j-log4j121.7.32slf4j-log4j12-1.7.32.jar;D:Maven Local Repositorylog4jlog4j1.2.17log4j-1.2.17.jar;D:Maven Local Repositorycglibcglib2.2.2cglib-2.2.2.jar;D:Maven Local Repositoryasmasm3.3.1asm-3.3.1.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 cn.cloud9.test.reflect.ReflectAndAnnotation,simpleGet
    before method run...
    A.fun executed... 
    after method run...
    class cn.cloud9.test.reflect.sample.A$$EnhancerByCGLIB$$fe34985a
    
    Process finished with exit code 0

    为什么获取不到?

    因为 这个是代理的对象,那么代理对象也应该由一个类来创建

    这个类是代理对象类  class cn.cloud9.test.reflect.sample.A$$EnhancerByCGLIB$$fe34985a ,那么代理对象类会有我们设置的注解吗?

    结果是没有的,但是根据CGLIB代理的实现原理,CGLIB代理原理是通过继承实现的,所以我们是不是可以通过代理类向上找父类来获取?

    下面就是对猜想的测试:

    package cn.cloud9.test.reflect;
    
    import cn.cloud9.test.reflect.sample.A;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import org.junit.Test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    public class ReflectAndAnnotation {
    
    
        @Test
        public void simpleGet() throws Exception {
    
            Class<?> aClass = Class.forName("cn.cloud9.test.reflect.sample.A");
    
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(aClass);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    System.out.println("before method run...");
                    Object result = proxy.invokeSuper(obj, args);
                    System.out.println("after method run...");
                    return result;
                }
            });
            A proxyA = (A) enhancer.create();
            proxyA.fun();
    
            Class<? extends A> proxyAClass = proxyA.getClass();
    
            System.out.println(proxyAClass);
    
            for (Annotation annotation : proxyAClass.getAnnotations()) {
                System.out.println(annotation);
            }
            
            // 获取父类
            Class<?> superclass1 = proxyAClass.getSuperclass();
            System.out.println(superclass1);
            for (Annotation annotation : superclass1.getAnnotations()) {
                System.out.println(annotation);
            }
        }
    }

    执行结果发现,代理对象的父类就是我们原来的类

    从原类再次获取注解,结果是可以的

    before method run...
    A.fun executed... 
    after method run...
    class cn.cloud9.test.reflect.sample.A$$EnhancerByCGLIB$$fe34985a
    class cn.cloud9.test.reflect.sample.A
    @cn.cloud9.test.reflect.annotation.AnnoA(value=)
    @cn.cloud9.test.reflect.annotation.AnnoB(value=)

    由此可以推断JDK的接口实现代理的方式

    对象要增强就需要通过接口实现处理,也就是说实际的接口对象,是实现类的对象

    注解在接口上,要通过实现类找到对应的接口,通过接口实例,再找到标注的注解

    注解在实现类上,就可以直接通过实现类,获取标注的注解

  • 相关阅读:
    Linux -- 查看是否安装了指定的包
    linux -- 部署java服务器(1) linux安装jdk
    spring boot -- 接收文件接口
    vue3 --相对于vue2的改变T1档次
    243交换输出
    24416进制的简单运算
    7街区最短路径问题
    206矩形的个数
    33蛇形填数
    273字母小游戏
  • 原文地址:https://www.cnblogs.com/mindzone/p/15467932.html
Copyright © 2011-2022 走看看