복붙노트

[SPRING] 스프링 싱글 톤 빈 필드가 채워지지 않습니다.

SPRING

스프링 싱글 톤 빈 필드가 채워지지 않습니다.

보류중인 스레드 목록 (예 : 모든 것이 스레드 안전성으로 작성 됨)과 같은 일부 내부 필드와 서비스 (싱글 톤 적합)가 필요합니다. 문제는이 빈에 대해 @autowire 필드가 비어있는 것처럼 보입니다. 디버깅 프록시가 채워진 필드가있는 인스턴스 (CGLIB $ CALLBACK_X 필드가 채워진 빈에 올바르게 연결되어 있음)에 올바르게 바인딩되지만 제공되는 필드는 비어 있습니다.

다음 코드 줄은 제가 무슨 말을하고 있는지에 대한 일반적인 아이디어를 제공합니다.

@Service
public class myService{

   @Autowired
   private Monitor monitor;

   public List getSomething(){
       return monitor.getList();
   }
}


@Service
public class myStatefulService{

   //This field will be populated for sure by someone before getSomething() is called
   private List list;

   public synchronized List getSomething(){
       return this.list;
   }

   //Called by other services that self inject this bean 
   public synchronized void addToList(Object o){
      this.list.add(o);
   }
}

내가 getList 호출하는 동안 변수 모니터 디버깅

monitor => instance of correct class
 fields:
   CGLIB$BOUND => true
   CGLIB$CALLBACK_0.advised => proxyFactory (correct)
   CGLIB$CALLBACK_1.target (reference to the correct instance of myStatefulService class)
        fields:
          list => [.........] (correctly populated)
   CGLIB$CALLBACK_2 ..... 
   ......
   ......
   ......
   list => [] (the list that would be populated is empty instead)

해결법

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

    1.호기심이 있거나 진짜 문제가 있습니까? 그럼에도 불구하고 여기에 설명이 있습니다.

    호기심이 있거나 진짜 문제가 있습니까? 그럼에도 불구하고 여기에 설명이 있습니다.

    CGLIB를 프록시 클래스로 사용하면 Spring은 myService $ EnhancerByCGLIB와 같은 서브 클래스를 생성합니다. 이 향상된 클래스는 실제 코드 주위에 교차 관심사를 적용하는 비즈니스 메소드 전부는 아니더라도 일부를 재정의합니다.

    여기에 놀라운 사실이 있습니다. 이 추가 서브 클래스는 기본 클래스의 수퍼 메소드를 호출하지 않습니다. 대신 myService의 두 번째 인스턴스를 만들고 여기에 delegate합니다. 즉, 실제 객체와 CGLIB 객체가 가리키는 (배치하는) 객체가 두 가지 있습니다.

    향상된 클래스는 단지 더미 프록시입니다. 여전히 기본 클래스 (상속 된 필드)와 동일한 필드가 있지만 사용되지 않습니다. myService $ EnhancerByCGLIB 객체에서 addToList ()를 호출하면 먼저 일부 AOP 논리를 적용하고 myService (add)를 호출하여 나머지 AOP 논리를 적용시 적용합니다. myService $ EnhancerByCGLIB.list 필드는 절대 건드리지 않습니다.

    Spring이 같은 클래스를 사용하고 수퍼를 통해 위임 할 수없는 이유는 무엇입니까? 단순함을 위해 다음과 같이 추측합니다. 먼저 "원시"bean을 작성한 후 사후 처리 중 AOP 프록 싱을 적용하십시오.

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

    2."이 필드는 getSomething ()이 호출되기 전에 누군가에 의해 확실하게 채워질 것입니다.

    "이 필드는 getSomething ()이 호출되기 전에 누군가에 의해 확실하게 채워질 것입니다.

    누군가에 의해? 아니, 봄 콩 공장. 구성하지 않으면 아무 것도 채워지지 않습니다.

    모든 bean이 Spring의 제어를받을 필요는 없습니다. 클라이언트가 스레드 안전 방식으로 항목을 추가하고 제거 할 수있는 목록을 갖고 싶어하는 것 같습니다. 맞으면 @Autowired 주석을 제거하고 새 List를 만들고 추가 및 제거 할 메소드를 노출하십시오.

    나는 새로운 동시 수집 목록을 권하고 싶습니다.

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

    3.CGLIB는 보호받는 게터를 프록시 처리합니다.

    CGLIB는 보호받는 게터를 프록시 처리합니다.

    그래서 당신은 가질 수 있습니다 :

    @Autowired
    private Monitor monitor;
    
    protected Monitor getMonitor() { return monitor; }
    
    public List getSomething(){
        return getMonitor().getList();
    }
    

    getMonitor ()는 모니터가 삽입 된 다른 인스턴스에서 getMonitor ()를 호출하도록 프록시 될 것입니다.

  4. from https://stackoverflow.com/questions/11580911/spring-singleton-bean-fields-are-not-populated by cc-by-sa and MIT license