developer tip

Spring은 추상 클래스 내부에서 autowire 할 수 있습니까?

copycodes 2020. 12. 31. 22:15
반응형

Spring은 추상 클래스 내부에서 autowire 할 수 있습니까?


Spring이 내 객체를 autowire하지 못합니까? 추상 클래스 내에서 객체를 자동 연결하는 것이 가능합니까? 모든 스키마가 application-context.xml에 제공된다고 가정합니다.

질문 : 기본 및 확장 클래스 (있는 경우) @Service @Component에 어떤 주석이 있어야합니까?

abstract class SuperMan {

    @Autowire
    private DatabaseService databaseService;

    abstract void Fly();

    protected void doSuperPowerAction(Thing thing) {

        //busy code

        databaseService.save(thing);

    }
}

클래스 확장

public class SuperGirl extends SuperMan {

    @Override
    public void Fly() {
        //busy code
    }

    public doSomethingSuperGirlDoes() {

        //busy code

        doSuperPowerAction(thing)

    }

application-context.xml

<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>

일반적으로 Spring은 추상 클래스가 컴포넌트 스캔을 위해 제공된 기본 패키지에있는 한 자동 연결을 수행해야합니다.

추가 참조를 위해 이것이것을 보십시오 .

@Service그리고 @ComponentSpring 컨테이너 내부에 주석이 달린 유형의 빈을 생성하는 스테레오 타입입니다. Spring Docs 상태에서

이 주석은 @Component의 특수화 역할을하여 구현 클래스가 클래스 경로 스캔을 통해 자동 감지되도록합니다.


그런 종류의 스프링 설정이 작동합니다.

autowired 필드가있는 추상 클래스

public abstract class AbstractJobRoute extends RouteBuilder {

    @Autowired
    private GlobalSettingsService settingsService;

@Component주석으로 정의 된 여러 하위 항목이 있습니다.


제 경우에는 Spring4 애플리케이션 내부에서 고전적인 추상 팩토리 패턴 ( http://java-design-patterns.com/patterns/abstract-factory/ 에서 아이디어를 가져옴 )을 사용하여 각각 인스턴스를 만들어야했습니다. 그리고 수행 할 작업이있을 때마다 내 코드는 다음과 같이 설계되었습니다.

public abstract class EO {
    @Autowired
    protected SmsNotificationService smsNotificationService;
    @Autowired
    protected SendEmailService sendEmailService;
    ...
    protected abstract void executeOperation(GenericMessage gMessage);
}

public final class OperationsExecutor {
    public enum OperationsType {
        ENROLL, CAMPAIGN
    }

    private OperationsExecutor() {
    }

    public static Object delegateOperation(OperationsType type, Object obj) 
    {
        switch(type) {
            case ENROLL:
                if (obj == null) {
                    return new EnrollOperation();
                }
                return EnrollOperation.validateRequestParams(obj);
            case CAMPAIGN:
                if (obj == null) {
                    return new CampaignOperation();
                }
                return CampaignOperation.validateRequestParams(obj);
            default:
                throw new IllegalArgumentException("OperationsType not supported.");
        }
    }
}

@Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
    @Override
    public void executeOperation(GenericMessage genericMessage) {
        LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
    }
}

Initially to inject the dependencies in the abstract class I tried all stereotype annotations like @Component, @Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **@Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.

<context:annotation-config />
<context:component-scan base-package="com.xyz" />

I also tried these other references to find a solution:

  1. http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
  2. http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
  3. https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
  4. http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
  5. https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
  6. Using abstract factory with Spring framework
  7. Spring Autowiring not working for Abstract classes
  8. Inject spring dependency in abstract super class
  9. Spring and Abstract class - injecting properties in abstract classes
    1. Spring autowire dependency defined in an abstract class

Please try using **@Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.


What if you need any database operation in SuperGirl you would inject it again into SuperGirl.

I think the main idea is using the same object reference in different classes. So what about this:

//There is no annotation about Spring in the abstract part.
abstract class SuperMan {


    private final DatabaseService databaseService;

    public SuperMan(DatabaseService databaseService) {
     this.databaseService = databaseService;
    }

    abstract void Fly();

    protected void doSuperPowerAction(Thing thing) {

        //busy code

        databaseService.save(thing);

    }
}

@Component
public class SuperGirl extends SuperMan {

private final DatabaseService databaseService;

@Autowired
public SuperGirl (DatabaseService databaseService) {
     super(databaseService);
     this.databaseService = databaseService;
    }

@Override
public void Fly() {
    //busy code
}

public doSomethingSuperGirlDoes() {

    //busy code

    doSuperPowerAction(thing)

}

In my opinion, inject once run everywhere :)

ReferenceURL : https://stackoverflow.com/questions/19965829/spring-can-you-autowire-inside-an-abstract-class

반응형