[W3D3]SpringBoot_part1

15804 단어 TILTIL

1. Dependency injection 방법

  • 전략패턴
  • 서비스 로케이터 패턴
  • 팩토리 패턴
  • 의존관계주입 패턴
    - 생성자 주입 패턴
    • 세터 주입 패턴

Circular dependencies
A → B를 참조하고 B → A를 참조할경우 순환 의존관계가 형성되면서
BeanCurrentlyInCreationException 예외가 발생할 수 있습니다.

package org.prgrms.kdtspringorder;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

class A{
    private final B b;

    A(B b){
        this.b = b;
    }
}

class B{
    private final A a;
    B(A a){
        this.a =a;
    }
}
@Configuration
class CircularConfig{
    @Bean
    public A a(B b){
        return new A(b);
    }

    @Bean
    B b(A a){
        return new B(a);
    }
}
public class CircularDepTester {
    public static void main(String[] args) {
        var AnnotationConfigApplicationContext = new AnnotationConfigApplicationContext(CircularConfig.class);
    }
}

2. 컴포넌트 스캔으로 빈 등록하기

  • 컴포넌트 스캔: 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능
  • 설정 클래스에 빈으로 직접 등록하지 않아도 원하는 클래스를 빈으로 등록가능
  • Stereotype 애노테이션을 이용하여 스프링은 자동으로 등록될 빈을 찾음(스캔대상을 지정할 수 있음)
    - @Component, @Controller, @Service, @Configuration

  1. @ComponetScan을 이용하면 @Bean 없이 빈으로 자동으로 등록

  1. -각각 인터페이스로부터 레포지토리를 구현함
    -컴포넌트 스캔대상으로 하기 위해 @Repository 추가
    -MemoryOrderRepository에서 getOrderId 사용하기 위해 Order클래스에 메서드 추가함
public UUID getOrderId(){
        return orderId;
    }

의존관계 주입 방법

  • 생성자

  • Autowired

-setter

의존관계 주입 방법에는 여러가지가 존재하는데 무엇을 써야할까? 생성자 기반 의존관계 주입 !!!
1 초기화시에 필요한 모든 의존관계가 형성되기 때문에 안전
2 잘못된 패턴 찾을수 있게 도와줌 : 생성자의 매개변수가 여러가지일경우 많은 의존관계를 맺고 있다고 암시 -> 관심사의 분리가 필요한 부분
3 테스트 쉽게해줌 :set 필드 로 의존주입할경우 생성안된 빈에 의해 널포인트예외 발생 가능성 있음
4 불면성을 확보 :생성자 주입을 안하면 final 키워드 불가능
final 키워드 : 한번 만들어진 의존관계가 변하지 않게 도와줌

똑같은 인터페이스를 구현한 클래스가 여러개면 ?

기존클래스에 VoucherRepository를 구현하는 JdbcVoucherRepository를 생성할 경우 둘다 @Repository가 있기 때문에 componentscan의 대상 두개의 빈이 등록 되기 때문에 아래와 같이 오류가 발생한다.

해결방법? 어떤 빈이 자동등록되는지 선택을 해줘야함 @Primary



1. @primary를 이용하여 빈 등록시 우선순위를 부여
2. 이름을 명시해주고
A서버 B서버 C서버에서 접속 대상이 다를경우
접속을 담당하는 탬플릿 클래스는 동일한데 3개가 등록 되어야함
다같은 타입이어서 충돌이 일어날때 이럴때 퀄리파이이용
대체로 프라이머리

Bean Scope

var voucherRepository = BeanFactoryAnnotationUtils.qualifiedBeanOfType(applicationContext.getBeanFactory(),VoucherRepository.class,"memory");
        var voucherRepository2 = BeanFactoryAnnotationUtils.qualifiedBeanOfType(applicationContext.getBeanFactory(),VoucherRepository.class,"memory");
        System.out.println(MessageFormat.format("voucherRepository {0}",voucherRepository));
        System.out.println(MessageFormat.format("voucherRepository2 {0}",voucherRepository));
        System.out.println(MessageFormat.format("voucherRepository == voucherRepository2 => {0}", voucherRepository == voucherRepository2));

getBean할때마다 같은 객체가 반환되는 것을 알수 있다. 다르게 하고 싶을때는 prototype을 이용하면 된다.

prototype을 이용했기 때문에 다른 객체가 반환되는 것을 확일할 수 있다.

실행결과

postConstruct called!
afterPropertieSet called!
main 실행
preDestroy called!
destroy called!
public class AppConfiguration {
    @Bean(initMethod = "init")
    public Beanone beanone(){
        return new Beanone();
    }
    class Beanone implements InitializingBean{

        public void init(){
            System.out.println("[BeanOne]init called");

        }
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("[Beanone] afterPropertiesSet called!");
        }

    }

좋은 웹페이지 즐겨찾기