복붙노트

[SPRING] URLClassLoader는 Annotation을 com.sun으로로드합니다. $ Proxy $ 27

SPRING

URLClassLoader는 Annotation을 com.sun으로로드합니다. $ Proxy $ 27

Java 클래스를 동적으로로드하려고합니다. 기본 개념은 런타임에 동적으로로드되는 모듈이 jar에 포함되어 있다는 것입니다. 이것은 내가하는 일이다. (hacky이지만, 이미 존재하는 클래스 로더 afaik에 jar를 동적으로 추가하는 다른 방법은 없다) :

Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
method.setAccessible(true);
method.invoke(moduleLoader, new Object[] { file.toURI().toURL() });
Class fooClass = moduleLoader.loadClass("com.coderunner.Foo");
Object foo = fooClass.newInstance();

모든 모듈은 @Module 주석으로 주석 처리됩니다. 따라서 모듈에 대한 추가 정보를 얻기 위해 주석을 얻으려고합니다. 문제는 foo에 대한 주석이 com.sun. $ Proxy $ 27 대신 com.coderunner.Module인데 따라서 나는

ClassCastException: Cannot cast com.sun.proxy.$Proxy42 (id=64) to com.coderunner.Module

나는 여기서 어떤 일이 일어날 지 혼란 스럽다. 내가하고 싶은 일이 가능합니까? 방법?

편집 : 나는 또한 봄 / 봄 - mvc 및 바람둥이 환경에서 이것을 시도하는 언급해야합니다.

해결법

  1. ==============================

    1.리플렉션이 프록시 객체를 반환한다는 사실은 사용자가 주석 및 해당 값에 대한 정보를 수집하는 것을 방해하지 않습니다.

    리플렉션이 프록시 객체를 반환한다는 사실은 사용자가 주석 및 해당 값에 대한 정보를 수집하는 것을 방해하지 않습니다.

    getclass 메소드는 프록시 객체를 반환합니다.

     log.info("annotation class:" + annotation.getClass());
    

    산출:

     [INFO] annotation class:class com.sun.proxy.$Proxy16class 
    

    결과는 귀하의 예와 동일하지만 아무런 문제가되지 않습니다. 메서드 (또는 필드)가 있으면 충분합니다. 추가 부분은 주석 메서드를 호출하는 것입니다.

    public void analyseClass(Class myClass) {
    
        for (Method method: myClass.getMethods()) {
            System.out.println("aanotations :" + Arrays.toString(field.getAnnotations()));
    
            for (Annotation annotation : method.getAnnotations()) {
    
                log.info("annotation class:" + annotation.getClass());
                log.info("annotation class type:" + annotation.annotationType());
    
                Class<Annotation> type = (Class<Annotation>) annotation.annotationType();
    
                /* extract info only for a certain annotation */
                if(type.getName().equals(MyAnnotation.class.getName())) {
    
                     String annotationValue = 
                         (String) type.getMethod("MY_ANNOTATION_CERTAIN_METHOD_NAME").invoke(annotation);
    
                     log.info("annotationValue :" + annotationValue);
                     break;
                }
            }
        }
    
        //do the same for the fields of the class
        for (Field field : myClass.getFields()) {
             //...
        }
    
    }  
    

    이 솔루션을 사용하기 위해 다음 게시물을 사용했습니다. 반영을 사용하여 주석 클래스 이름, 속성 값을 얻는 방법

  2. ==============================

    2.어노테이션 유형 앞에 프록시를 추가해야한다는 사실은 중요하지 않습니다. 이것이 실제로 당신이 가지고있는 문제의 원인이라고 믿게 만들 수도 있습니다. "isAnnotationPresent (..)"와 같은 항목이 실패하면, 그 프록시 때문이 아니라 여러 클래스 로더를 사용하여 주석 클래스를 여러 번로드했기 때문입니다. 예를 들어, Jetty는 기본적으로 WebApp 클래스 로더에 우선 순위를 부여합니다. 따라서 Jetty 서버 인스턴스 (또는 Tomcat 또는 기타)가 이미 주석 클래스를로드하고 주석이 웹 애플리케이션의 클래스 경로에있는 경우 "getAnnotation ()"이 반환하지 않는 것과 같은 문제가 발생할 수 있습니다. 어노테이션이 들어있는 라이브러리가 두 번로드되지 않았는지 확인하십시오.

    어노테이션 유형 앞에 프록시를 추가해야한다는 사실은 중요하지 않습니다. 이것이 실제로 당신이 가지고있는 문제의 원인이라고 믿게 만들 수도 있습니다. "isAnnotationPresent (..)"와 같은 항목이 실패하면, 그 프록시 때문이 아니라 여러 클래스 로더를 사용하여 주석 클래스를 여러 번로드했기 때문입니다. 예를 들어, Jetty는 기본적으로 WebApp 클래스 로더에 우선 순위를 부여합니다. 따라서 Jetty 서버 인스턴스 (또는 Tomcat 또는 기타)가 이미 주석 클래스를로드하고 주석이 웹 애플리케이션의 클래스 경로에있는 경우 "getAnnotation ()"이 반환하지 않는 것과 같은 문제가 발생할 수 있습니다. 어노테이션이 들어있는 라이브러리가 두 번로드되지 않았는지 확인하십시오.

    Andreas가 제공하는 솔루션은 매우 더러운 해결 방법이며, 클래스 로딩을 제어 / 적절하게 구성하지 않았을 수도 있습니다.

  3. ==============================

    3.어노테이션을 사용하는 선언적 접근 방식을 기반으로 코드 생성을위한 앤트 작업을 만들려고 할 때도 동일한 문제가있었습니다. Proxyof-Object의 문서에서 instanceof가 문제를 해결해야한다는 것을 알았습니다. 그러나 이것은 나에게도 효과가 없었습니다. 나는 마침내 주위에있어

    어노테이션을 사용하는 선언적 접근 방식을 기반으로 코드 생성을위한 앤트 작업을 만들려고 할 때도 동일한 문제가있었습니다. Proxyof-Object의 문서에서 instanceof가 문제를 해결해야한다는 것을 알았습니다. 그러나 이것은 나에게도 효과가 없었습니다. 나는 마침내 주위에있어

    Annotation [] annotations = classObj.getAnnotations ();

        for(int i = 0;i < annotations.length;i++) {
            Class<?>[] interfaces = annotations[i].getClass().getInterfaces();
    
            for(int i2 = 0; i2 < interfaces.length;i2++) {
                System.out.println("interface:" + interfaces[i2].getName());
            }
    

  4. from https://stackoverflow.com/questions/18282337/urlclassloader-loads-annotation-as-com-sun-proxy27 by cc-by-sa and MIT license