2010-04-05 4 views
11

나는이 질문에앱 서버가 비공개 필드에 어떻게 삽입합니까?

수동

그러나 (방법이 나 생성자를 통해 세터 을 추가) 주석 개인 필드에 주입하는 방법에 대한

Inject into private, package or public field or provide a setter?

을 보았다는 점은 응용 프로그램 서버를 수행하는 방법이다 (glassfish, axis2, jboss, ...) 은 (사용자 클래스에 setter 또는 생성자를 추가하지 않고) 마지막 개인 필드에 주입 할 수 있습니까? ?

public SomeClass { 
    @Inject 
    private SomeResource resource; 
} 

들이 사용자 정의 된 JVM (하지 표준 하나) 사용하십니까 private 필드에 액세스 할 수 있습니다 :

인용 된 질문을 인용?

감사합니다.

+0

이것은 사적이지만 최종적은 아닙니다. 코드 블록에서 * final *을 놓치셨습니까? 나는 개인 최종 회원을 투입하는 것이 가능하지 않기 때문에. (내가 틀렸다면 나를 바로 잡아라.) – whiskeysierra

+0

@ 윌리 : 네 말이 맞아. 아래의 코드 샘플에서는 final을 넣었지만 doInjection() 메서드로 오류를 발생시키지 않았으므로 값은 변경되지 않았습니다. 그래서 나는 마지막을 제거했다. – cibercitizen1

답변

16

간단한 반사 "트릭"입니다. 이 프로그램에 액세스 할 수 있도록 구성원을 강제로 Field.setAccessible() 방법에 의존 :

은 지정된 부울 값이 객체의 accessible 플래그를 설정합니다. true 값은 반사 객체가 일 때 Java 언어 액세스 검사를 억제해야 함을 나타냅니다. 값이 false이면 반사 개체가 Java 언어 액세스 검사를 시행해야 함을 나타냅니다.

Reflection API는 필드에서 핸들을 얻는 데 사용되며 setAccessible()이 호출 된 다음 주입 프레임 워크에서 설정할 수 있습니다.

예 : here을 참조하십시오.

마술이없고 사용자 지정 VM이 없습니다.

+0

@skaffman 아주 좋습니다! – cibercitizen1

+0

고마워,하지만 나는 그것에 대한 크레딧을받을 수 없어 :) – skaffman

6

skaffman의 도움으로 저는이 간단한 예제를 세터없이 주입하는 방법을 코딩했습니다. 는 아마도

//...................................................... 
import java.lang.annotation.*; 
import java.lang.reflect.*; 

//...................................................... 
@Target(value = {ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME) 
@interface Inject { 
} 

//...................................................... 
class MyClass { 

    @Inject 
    private int theValue = 0; 

    public int getTheValue() { 
     return theValue; 
    } 
} // class 

//...................................................... 
public class Example { 

    //...................................................... 
    private static void doTheInjection(MyClass u, int value) throws IllegalAccessException { 

     Field[] camps = u.getClass().getDeclaredFields(); 

     System.out.println("------- fields : --------"); 
     for (Field f : camps) { 
      System.out.println(" -> " + f.toString()); 
      Annotation an = f.getAnnotation(Inject.class); 
      if (an != null) { 
       System.out.println("  found annotation: " + an.toString()); 
       System.out.println("  injecting !"); 
       f.setAccessible(true); 
       f.set(u, value); 
       f.setAccessible(false); 
      } 
     } 

    } //() 

    //...................................................... 
    public static void main(String[] args) throws Exception { 

     MyClass u = new MyClass(); 

     doTheInjection(u, 23); 

     System.out.println(u.getTheValue()); 

    } // main() 
} // class 

실행 출력 (그것은 한 나에게) 도움 :

------- fields : -------- 
-> private int MyClass.theValue 
     found annotation: @Inject() 
     injecting ! 
23 
3

그것은 어떤 프레임 워크는 비용없이 같은 결과를 달성하기 위해 사용자 정의 클래스 로더를 통해 바이트 코드 기술을 활용하는 것이 또한 주목할만한 가치가 반사 (반사는 꽤 비쌀 수 있음)

관련 문제