JUST WRITE

@Autowired 본문

Programing/Spring

@Autowired

천재보단범재 2021. 10. 22. 17:49
이 글은 Baeldung 사이트 'Guide to Spring @Autowired'를 해석, 정리한 글입니다.

 

@Autowired

Spring 2.5부터 Annotation를 통한 의존성 주입이 가능해졌다.

@Autowired라는 Annotation을 통해 가능해졌다.

@Autowired 준비

Spring Framework는 자동 의존성 주입이 가능하다.

Spring 설정 파일에 Bean 의존성들을 정의하고 Spring Container가 의존성 Bean들을 자동으로 주입해준다.

Annotation를 통한 의존성을 주입을 하려면 아래와 같이 정의한다.

Java Configuration

@Configuration
@ComponentScan("com.baeldung.autowire.sample")
public class AppConfig {}

XML Configuration

<context:annotation-config>

Spring Boot에서는 @SpringBootApplication Annotation을 사용한다.

@Configuration + @EnableAutoConfiguration + @ComponentScan을 합친 Annotation이다.

@SpringBootApplication
class VehicleFactoryApplication {
    public static void main(String[] args) {
        SpringApplication.run(VehicleFactoryApplication.class, args);
    }
}

그럼 자동적으로 현재 Package와 하위 Package에 있는 Component들을 검색할 것이다.

@Autowired 사용

Spring에서는 Property, Setter, Constructor에서 @Autowired를 사용할 수 있다.

Property

Property에서 @Autowired를 사용할 수 있다.

대신 Getter와 Setter를 제거해줘야 한다.

// Bean Define
@Component("fooFormatter")
public class FooFormatter {
    public String format() {
        return "foo";
    }
}

@Component
public class FooService {  
    @Autowired // Property에 Autowired
    private FooFormatter fooFormatter; 
}

Setter

Setter에서 @Autowired를 사용할 수 있다.

public class FooService {
    private FooFormatter fooFormatter;
    @Autowired // Setter에 Autowired
    public void setFooFormatter(FooFormatter fooFormatter) {
        this.fooFormatter = fooFormatter;
    }
}

Constructor

Constructor에서 @Autowired를 사용할 수 있다.

public class FooService {
    private FooFormatter fooFormatter;
    @Autowired // Constructor에 Autowired
    public FooService(FooFormatter fooFormatter) {
        this.fooFormatter = fooFormatter;
    }
}

Option 처리

Spring Bean이 생성할 때 Autowired된 다른 Bean이 의존성 주입되어야 한다.

그때 주입이 될 수 없으면 NoSuchBeanDefinitionException이 발생한다.

그걸 방지하기 위해서 Required라는 옵션 처리가 가능하다.

public class FooService {
    @Autowired(required = false) // 해당 Bean 없으면 No wired
    private FooDAO dataAccessor; 
}

Autowired Bean Conflict

@Autowired는 기본적으로 Type으로 Bean을 찾아서 주입한다.

Spring Container에 같은 Type의 Bean이 2개 이상이면 NoUniqueBeanDefinitionException이 발생한다.

@Component("fooFormatter")
public class FooFormatter implements Formatter {
    public String format() {
        return "foo";
    }
}

@Component("barFormatter")
public class BarFormatter implements Formatter {
    public String format() {
        return "bar";
    }
}

public class FooService {
    @Autowired // FooFormatter, BarFormatter 넣을지 판단 X
    private Formatter formatter;
}

@Qualifier

이 이슈를 해결하기 위해서는 @Qualifier라는 Annotation을 같이 사용해서 해결한다.

Qualifiet Annotation에 Bean 이름을 명시하여 넣을 Bean을 명확하게 해 준다.

public class FooService {
    @Autowired
    @Qualifier("fooFormatter") // fooFormatter라는 Bean이 Autowired
    private Formatter formatter;
}

@Qualifier Custom

@Qualifier Annotation을 Custom 할 수 있다.

@Qualifier
@Target({
  ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatterType {  
    String value();
}
@FormatterType("Foo")
@Component
public class FooFormatter implements Formatter {
    public String format() {
        return "foo";
    }
}

@FormatterType("Bar")
@Component
public class BarFormatter implements Formatter {
    public String format() {
        return "bar";
    }
}

@Component
public class FooService {  
    @Autowired
    @FormatterType("Foo")
    private Formatter formatter;
}

@Primary

@Primary Annotation을 통해서 위 이슈를 해결할 수 있다.

같은 Type Bean이 여러 개 있을 때 @Primary로 특정 Bean을 대표 Bean으로 설정할 수 있다.

@Configuration
public class Config {
 
    @Bean
    public Employee johnEmployee() {
        return new Employee("John");
    }
 
    @Bean
    @Primary
    public Employee tonyEmployee() {
        return new Employee("Tony");
    }
}


public class EmployeeService {
    @Autowired // Primary인 tonyEmployee Autowired
    private Employee employee;
}

Autowiring by Name

기본적으로 Spring은 Bean 이름과 Property명이 같은 것을 찾는다.

@Component("fooFormatter")
public class FooFormatter implements Formatter {
    public String format() {
        return "foo";
    }
}

@Component("barFormatter")
public class BarFormatter implements Formatter {
    public String format() {
        return "bar";
    }
}

public class FooService {
    @Autowired // Bean이름과 동일한 FooFormatter로 Autowired
    private Formatter fooFormatter;
}
728x90
반응형

'Programing > Spring' 카테고리의 다른 글

BeanFactory vs ApplicationContext  (0) 2021.12.21
Bean Annotations  (0) 2021.12.20
DispatcherSerlvet  (0) 2021.10.15
MappingJackson2JsonView  (0) 2021.10.09
Singleton Registry  (0) 2021.10.02
Comments