복붙노트

[SPRING] 스프링 @Autowired 클래스의 새 인스턴스

SPRING

스프링 @Autowired 클래스의 새 인스턴스

나는 봄에 익숙하지 않고 다음과 같은 상황에 처해있다.

저장소 클래스 :

@Repository
public class MyRepository {
    // ...
}

저장소 클래스를 사용하는 클래스 :

public class MyClass extends AbstractClass {

    @Autowired
    private MyRepository myRepository;

    //...
}

내 MyClass에 @Component 주석을 달고 @Autowired와 함께 사용하면 @Autowired MyRepository가 제대로 처리된다는 것을 알고 있습니다. 문제는 리플렉션을 통해 MyClass의 새 인스턴스를 만들어야하는 상황에 있습니다. 따라서 MyRepository는 해결되지 않으며 항상 null입니다.

이 상황에서 @Autowired를 사용할 수있는 방법이 있습니까?

더 나은 내 상황을 설명 : 나는 추상적 클래스의 구현을 가지고있다. 내 응용 프로그램의 설치 단계에서 이러한 구현의 HashMap을 만듭니다. 원래:

{"MyClass", MyClass.class}
//...

그런 다음 url / {class}? options =에 매핑되는 일반 컨트롤러가 있습니다. {class} @PathVariable, 위의 HashMap 및 리플렉션을 사용하여 주어진 옵션을 기반으로 클래스의 인스턴스를 만들 수 있습니다 (이 부분은 중요 함). 너 더 나은 방법이 있다고 생각하니?

미리 감사드립니다.

해결법

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

    1.Spring 자체는 객체에서 자동 배선을 수행하는 몇 가지 기능을 제공합니다. new 또는 newInstance () 등으로 만든 클래스입니다.

    Spring 자체는 객체에서 자동 배선을 수행하는 몇 가지 기능을 제공합니다. new 또는 newInstance () 등으로 만든 클래스입니다.

    그것을 사용하려면 AutowireCapableBeanFactory가 필요합니다. @Autowired와 함께 Spring의 정상적인 의존성 주입으로 얻을 수있다.

    @Autowired
    private  AutowireCapableBeanFactory autowireCapableBeanFactory;
    

    그런 다음 autowireBean (Object) 메소드를 사용합니다. @Autowired 속성을 빈에 삽입한다.

    Object myBean = map.get(className).newInstance();
    autowireCapableBeanFactory.autowireBean(myBean);
    

    디자인 노트 :

    위의 접근 방식이 정말로 필요하면 잘 생각하십시오. AutowireCapableBeanFactory의 javadoc은 대부분의 유스 케이스에서이 인터페이스를 사용하지 말 것을 권고합니다.

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

    2.한 가지 해결 방법은 MyClass를 Hashmap에 바인딩하여 Factory 클래스를 바인딩하는 것이 아닙니다. MyClassFactory. 이렇게하면 올바른 클래스를 인스턴스화하고 올바른 저장소를 초기화하는 작업을 수행하는 구체적인 팩토리에 구성을 위임하게됩니다.

    한 가지 해결 방법은 MyClass를 Hashmap에 바인딩하여 Factory 클래스를 바인딩하는 것이 아닙니다. MyClassFactory. 이렇게하면 올바른 클래스를 인스턴스화하고 올바른 저장소를 초기화하는 작업을 수행하는 구체적인 팩토리에 구성을 위임하게됩니다.

    다음은 그 예입니다.

    {"MyClass", MyClassFactory.class}
    

    팩토리는 Component가 될 수 있습니다. 그러면 해시 맵을 팩토리 클래스 대신 팩토리 인스턴스에 바인딩해야합니다. 그러나 이것이 구성 요소가 아니라고 말할 수 있습니다.

    //@Component   this is optional
        public MyClassFactory {
            //@Autowired optional
            ApplicationContext ctx;
    
    
           public MyClass createInstance() {
                MyRepository repo = ctx.getBean("")
                MyClass myclass = new MyClass(repo)
                return myclass;
           }
        }
    

    컴포넌트로 표시하면 ApplicationContext를 autowire 할 경우에도 ApplicationContextAware 인터페이스를 사용할 수 있습니다.

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

    3.한 가지 방법은 @Component를 MyClass 위에 선언하는 것입니다.

    한 가지 방법은 @Component를 MyClass 위에 선언하는 것입니다.

    그런 다음 설치 단계에서 MyClass.class 자체 대신 MyClass의 인스턴스를 HashMap에 전달할 수 있습니다. 리플렉션을 통해 인스턴스를 만들 필요가 없습니다.

    참고 : 설정 단계에서 ApplicationContext로부터 MyClass의 인스턴스를 가져올 수 있습니다.

  4. ==============================

    4.이 시도

    이 시도

    @Component    
    public class SomeClass extends AbstractClass {
    
      private static ApplicationContext applicationContext;
    
      public MyClass getMyClass(){
          // Now @Autowired MyRepository will work
          return applicationContext.getBean(MyClass.class);
      }
    
    }
    
  5. ==============================

    5.여기에 Factory Design Pattern을 사용할 수 있습니다.

    여기에 Factory Design Pattern을 사용할 수 있습니다.

    이것은 처음에는 조금 복잡해 보일지 모르지만, 구현 한 후에는 그것을 좋아할 것이라고 확신합니다.

    단계 :

    이 MyFactory 클래스의 Bean이 초기화되면, AbstractClass 타입의 모든 빈을 찾아서 HashMap (implementationMap)에 넣을 것이다.

    이제이 팩토리에서 HashMap을 가져 와서 필요할 때 구현을 가져올 수 있습니다. 팩토리가 처리 할 때마다 AbstractClass의 새로운 구현을 추가하면 매우 쉽습니다.

  6. ==============================

    6.예, 모든 AbstractClass 구현 빈에 @Component 주석을 달고 다음 선언을 사용할 수 있습니다.

    예, 모든 AbstractClass 구현 빈에 @Component 주석을 달고 다음 선언을 사용할 수 있습니다.

    @Autowired
    private List<AbstractClass> beans;
    

    그런 다음이를 @PostConstruct 메소드의 Map으로 변환 할 수 있습니다.

    List를 autowire하면 Spring은 중복 정의에 대해 불평하지 않을 것이다.

  7. from https://stackoverflow.com/questions/52355132/spring-autowired-on-a-class-new-instance by cc-by-sa and MIT license