2023. 12. 10. 23:16ㆍspring
과제
애플리케이션을 구성하는 POJO/빈 인스턴스들은 서로 함께 움직여 임무를 완수합니다. 애너테이션을 붙여 POJO 레퍼런스와 자동 연결하세요
해결책
자바 구성 클래스에 정의된 POJO/빈 인스턴스들 사이의 참조 관계는 표준 자바 코드로도 맨어줄 수 있다.
필드, 세터 메서드, 생성자, 또는 아무 다른 메서드에 @Autowired를 붙이면 POJO레퍼런스를 자동 연결해 쓸 수 있다.
풀이
생성자, 필드, 프로퍼티로 자동 연결하는 방법을 차례로 소개하고 마지막에 자동 연결 관련 이슈의 해결 방법을 제시합니다.
자바 구성 클래스에서 POJO 참조하기
자바 구성 클래스에 POJO 인스턴스를 정의하면, 모든 게 자바 코드로 있으니 얼마든지 POJO를 참조할 수 있다.
@Configuration
public class SequenceGeneratorConfiguration {
@Bean
public Sequence sequence() {
Sequence sequence = new Sequence();
sequence.setId(sequenceGenerator().getSequence());
return sequence;
}
@Bean
SequenceGenerator sequenceGenerator() {
SequenceGenerator seqgen = new SequenceGenerator();
seqgen.setPrefix("30");
seqgen.setSuffix("A");
seqgen.setInitial(100000);
return seqgen;
}
}
POJO 필드에 @Autowired를 붙여 자동 연결하기
@Component
public class SequenceService {
@Autowired
private SequenceDao sequenceDao;
public void setSequenceDao(SequenceDao sequenceDao) {
this.sequenceDao = sequenceDao;
}
public String generate(String sequenceId) {
Sequence sequence = sequenceDao.getSequence(sequenceId);
int value = sequenceDao.getNextValue(sequenceId);
return sequence.getPrefix() + value + sequence.getSuffix();
}
}
SequenceService 클래스는 @Component를 붙였기 때문에 스프링 빈으로 등록된다.
그리고 sequenceDao 프로퍼티에 @Autowired가 있기 때문에 sequenceDao 빈이 이 프로퍼티에 자동 연결된다.
이것 외에도 배열, 리스트, 맵 등 컬렉션에 @Autowired를 붙이면 스프링은 이 컬렉션과 타입 호환되는 빈을 모두 찾아 연결한다.
public class SequenceGenerator {
@Autowired
private PrefixGenerator[] generatorArray;
@Autowired
private List<PrefixGenerator> generatorList;
@Autowired
private Map<String, PrefixGenerator> generatorMap;
}
@Autowired로 POJO 메서드와 생성자를 자동 연결하기, 자동 연결을 선택적으로 적용하기
@Autowired는 POJO 세터 메서드에도 직접 적용할 수 있다.
@Autowired
public void setSequenceDao(SequenceDao sequenceDao) {
this.sequenceDao = sequenceDao;
}
스프링은 기본적으로 @Autowired를 붙인 필수 프로퍼티에 해당하는 빈을 찾지 못하면 예외를 던진다. 따라서 선택적인 프로퍼티는 @Autowired 속성 값을 false로 지정해 스프링이 빈을 못 찾더라도 그냥 지나치게 한다.
@Autowired(required = false)
public void setSequenceDao(SequenceDao sequenceDao) {
this.sequenceDao = sequenceDao;
}
@Autowired는 메서드 인수의 이름과 개수에 상관없이 적용할 수 있고 생성자에도 적용할 수 있다.
@Component
public class SequenceService {
private final SequenceDao sequenceDao;
@Autowired
public SequenceService(SequenceDao sequenceDao) {
this.sequenceDao = sequenceDao;
}
public String generate(String sequenceId) {
Sequence sequence = sequenceDao.getSequence(sequenceId);
int value = sequenceDao.getNextValue(sequenceId);
return sequence.getPrefix() + value + sequence.getSuffix();
}
}
애너테이션으로 모호한 자동 연결 명시하기
타입을 기준으로 자동 연결하면 IoC 컨에이너에 호환 타입이 여럿 존재하거나 프로퍼티가 (배열, 리트스, 맵 등의) 그룹형이 아닐 경우 제대로 연결되지 않는다.
타입이 같은 빈의 경우 @Primary, @Qualifier로 해결할 수 있다.
@Primary로 모호한 자동 연결 명시
@Primary를 붙여 후보 빈을 명시한다. 여러 빈이 자동 연결 대상일 때 특정한 빈에 우선권을 부여한다.
@Component
@Primary
public class SequenceService {
private final SequenceDao sequenceDao;
@Autowired
public SequenceService(SequenceDao sequenceDao) {
this.sequenceDao = sequenceDao;
}
public String generate(String sequenceId) {
Sequence sequence = sequenceDao.getSequence(sequenceId);
int value = sequenceDao.getNextValue(sequenceId);
return sequence.getPrefix() + value + sequence.getSuffix();
}
}
@Qualifier로 모호한 자동 연결 명시
@Qualifier에 이름을 주어 후보 빈을 명시할 수 있다.
@Component
@Primary
public class SequenceService {
private final SequenceDao sequenceDao;
@Autowired
@Qualifier("sequenceDao")
public SequenceService(SequenceDao sequenceDao) {
this.sequenceDao = sequenceDao;
}
public String generate(String sequenceId) {
Sequence sequence = sequenceDao.getSequence(sequenceId);
int value = sequenceDao.getNextValue(sequenceId);
return sequence.getPrefix() + value + sequence.getSuffix();
}
}
이렇게 하면 스프링은 IoC 컨테이너에서 이름이 sequenceDao인 빈을 찾아 프로퍼티에 연결한다.
여러 곳에 분산된 POJO 참조 문제 해결하기
애플리케이션의 규모가 커질수록 모든 POJO 설정을 하나의 자바 구성 클래스에 담아두기 어렵기 때문에 보통 POJO 기능에 따라 여러 자바 구성 클래스로 나누어 관리한다.
그렇지만 자바 구성 클래스가 여럿 공존하면 상이한 클래스에 정의된 POJO를 자동 연결하거나 참조하는 일이 생각보다 그리 간단하지 않다.
한 가지 방법은 자바 구성 클래스가 위치한 경로바다 애플리케이션 컨텍스트를 초기화하는 것이다.
각 자바 구성 클래스에 선언된 POJO를 컨텍스트와 레퍼런스로 읽으면 POJO 간 자동 연결이 가능하다.
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(
SequenceConfig.class,
SequenceGeneratorConfiguration.class
);
}
@Import로 구성 파일을 나누어 임포트하는 방법도 있다.
@Configuration
@Import(SequenceConfig.class)
public class SequenceGeneratorConfiguration {
@Value("#{uniqueSequence}")
private Sequence sequence;
@Bean
public Sequence sequence() {
sequence.setId(sequenceGenerator().getSequence());
return sequence;
}
@Bean
SequenceGenerator sequenceGenerator() {
SequenceGenerator seqgen = new SequenceGenerator();
seqgen.setPrefix("30");
seqgen.setSuffix("A");
seqgen.setInitial(100000);
return seqgen;
}
}
'spring' 카테고리의 다른 글
스프링 레시피 CH2.6 외부 리소스(텍스트, XML, 프로퍼티, 이미지 파일)의 데이터 사용하기 (1) | 2023.12.12 |
---|---|
스프링 레시피 CH2.4 @Resource와 @Inject를 붙여 POJO 자동 연결 하기 (0) | 2023.12.11 |
스프링 레시피 CH2.2 생성자 호출해서 POJO 생성하기 (0) | 2023.12.10 |
스프링 레시피 CH2.1 자바로 POJO 구성하기 (0) | 2023.12.10 |
AOP란? (0) | 2022.05.28 |