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
그리고 @Component
Spring 컨테이너 내부에 주석이 달린 유형의 빈을 생성하는 스테레오 타입입니다. 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:
- http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
- http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
- https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
- http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
- https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
- Using abstract factory with Spring framework
- Spring Autowiring not working for Abstract classes
- Inject spring dependency in abstract super class
- Spring and Abstract class - injecting properties in abstract classes
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
'developer tip' 카테고리의 다른 글
n 차원 그리드 유형에 대한 cojoin 또는 cobind 작성 (0) | 2020.12.31 |
---|---|
윤활유가있는 날짜 순서 (0) | 2020.12.31 |
Python에서 웹캠에 어떻게 액세스합니까? (0) | 2020.12.31 |
Android TextView에서 지원하는 HTML 태그는 무엇입니까? (0) | 2020.12.31 |
cronjob 대 리눅스의 데몬. (0) | 2020.12.31 |