programing

추상 클래스 및 하위에 생성자 주입

goodsources 2023. 8. 19. 10:14
반응형

추상 클래스 및 하위에 생성자 주입

저는 다음과 같은 수업이 있습니다.

@Component
public abstract class NotificationCenter {
    protected final EmailService emailService;
    protected final Logger log = LoggerFactory.getLogger(getClass());

    protected NotificationCenter(EmailService emailService) {
        this.emailService = emailService;
    }

    protected void notifyOverEmail(String email, String message) {
        //do some work
        emailService.send(email, message);
    }
}

EmailService입니다.@Service생성자 주입에 의해 자동으로 배선되어야 합니다.

이제 나는 연장 수업이 있습니다.NotificationCenter 자동 구성 요소를 자동으로 해야 합니다.

@Service
public class NotificationCenterA extends NotificationCenter {    
    private final TemplateBuildingService templateBuildingService;

    public NotificationCenterA(TemplateBuildingService templateBuildingService) {
        this.templateBuildingService = templateBuildingService;
    }
}

, 추상 " 위예에따르면추클상래기에스생본없성않때다"에 기본 가 없기 NotificationCenter추가하지 않는 한super(emailService); 진번서로술에 대한 첫 로서.NotificationCenterA컨스트럭터 하지만 저는 그 예를 가지고 있지 않습니다.emailService아이들로부터 베이스 필드를 채울 생각은 없습니다

이 상황을 어떻게 처리해야 할지 아십니까?제가 현장 주사를 사용해야 할까요?

NotificationCenter실제 클래스가 아니라 추상 클래스이므로 인스턴스를 만들 수 없습니다.반면에 필드(최종 필드!)가 있습니다.EmailService생성자에서 초기화해야 합니다!최종 필드는 정확히 한 번만 초기화되기 때문에 세터는 여기서 작동하지 않습니다.봄도 아니고 자바야.

확되는모클스래든을 하는 모든 NotificationCenter 자식이 "알림 센터"이므로 EmailService 필드를 상속합니다.

따라서 초기화를 위해 이메일 서비스의 인스턴스를 가져와 super에 전달하는 생성자를 제공해야 합니다.봄이 아니라 자바입니다.

public class NotificationCenterA extends NotificationCenter {    
    private final TemplateBuildingService templateBuildingService;

    public NotificationCenterA(EmailService emailService, TemplateBuildingService templateBuildingService) {
       super(emailService);
       this.templateBuildingService = templateBuildingService;
    }
} 

이제 봄은 여러분을 위해 콩을 관리하고, 콩을 초기화하고 의존성을 주입합니다.당신은 솔직히 내가 이해하지 못하는 것을 씁니다.

...NotificationCenterA 생성자에 대한 첫 번째 설명이지만 e-메일 서비스의 인스턴스가 없으며 하위 항목에서 기본 필드를 채울 의도도 없습니다.

하지만 봄은 오직 한가지만 관리할 것입니다.NotificationCenterA EmailService 은 추상적인 클래스를 , 위에서 에, 될 합니다: Bean (EmailService 구현은그며을으않이가지하상리추관래를스클같적대사다질직대때용하기문에에문유한적접인가있음음과항은답에습니다서위한제설명한리고물론▁java▁bean가을▁be이▁will:▁ofservice),ation▁question▁(bean▁the▁think▁i▁emailand,

  1. 이 경우 세터 주입을 사용할 수 없습니다(다시 말하지만, 최종적으로, 그것은 봄 때문이 아니라 자바입니다).
  2. 일반적인 경우에 세터 주입보다 컨스트럭터 주입이 정확하게 처리할 수 있습니다.

첫 번째 점:

@Component사용자가 명시적으로 구현할 추상 클래스에서 사용하도록 설계되지 않았습니다.추상 클래스는 추상적이므로 구성 요소가 될 수 없습니다.
그것을 제거하고 다음 점을 고려합니다.

두 번째 포인트:

저는 아이들로부터 기본 필드를 채울 생각은 없습니다.

Spring과 DI가 없으면 부모 클래스에서 직접 종속성을 하드 코딩할 수 있지만 바람직한 것입니까?사실 그렇지 않아요.따라서 종속성이 숨겨지고 하위 클래스 또는 테스트용으로 다른 구현으로 전환하는 것이 훨씬 더 복잡해집니다.
따라서 하위 클래스에 종속성을 주입하고 주입된 EmailService를 상위 생성자에 전달하는 것이 올바른 방법입니다.

@Service
public class NotificationCenterA extends NotificationCenter {    
    private final TemplateBuildingService templateBuildingService;    

    public NotificationCenterA(TemplateBuildingService templateBuildingService, EmailService emailService) {
        super(emailService);
        this.templateBuildingService = templateBuildingService;
    }
}

그리고 부모님 수업에서는 그냥 쓸모없는 것들을 제거하세요.@Component주석

이 상황을 어떻게 처리해야 할지 아십니까?제가 현장 주사를 사용해야 할까요?

코드 테스트/유연성이 떨어지고 명확해지는 것은 아닙니다.

당신이 가지고 싶지 않다고 말했기 때문에 필드 주입을 사용하는 것이 좋은 방법일 것입니다.emailService아동반에서

당신이 시도할 수 있는 다른 방법은 주사하는 것입니다.EmailService에 빠지다NotificationCenterA생성자, 그리고 그것을 전달합니다.super(emailService).

따라서 다음과 같습니다.

        @Autowired
        public NotificationCenterA(EmailService emailService, TemplateBuildingService templateBuildingService) {
            super(emailService);
            this.templateBuildingService = templateBuildingService;
        }

또한 다음을 사용하여 이를 달성할 수 있습니다.@Lookup주석

public abstract class NotificationCenter {
    protected final Logger log = LoggerFactory.getLogger(getClass());

    @Lookup
    protected EmailService getEmailService() {
        return null; // Spring will implement this @Lookup method using a proxy
    }

    protected void notifyOverEmail(String email, String message) {
        //do some work
        EmailService emailService = getEmailService(); // This is return the service bean.
        emailService.send(email, message);
    }
}

언급URL : https://stackoverflow.com/questions/53049848/constructor-injection-on-abstract-class-and-children

반응형