명시적 DI
📌 @Component 라고 선언된 클래스는 바로 Bean이 되는 것은 아니고, @ComponentScan을 통한 Scan 과정을 거쳐서 Bean으로 등록된다.
@Component
@Component
public class LPhone{}
@Component
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default ""; // 생성되는 Bean의 이름을 재정의 하려는 경우에 사용
}
pascal case : IronMan => ironMan
pascal case 가 아닌 경우 : SPhone => SPhone
@Autowired
@Autowired
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
@ComponentScan
@Configuration
@ComponentScan({"com.hello.phone"})
public class PhoneConfig {
}
@Qualifier
Qualifier
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
📌 주의 ) Qualifier의 Target을 보면 Constructor가 없다. @Autowired가 생성자에 사용되기 때문에 같이 쓰는 실수를 할 때가 많은데, 생성자의 파라미터에 적용해주어야 한다.
적용코드
@Autowired
public Avengers(@Qualifier("ironMan") IronMan iman, Hulk hulk) {
this.iman = iman;
this.hulk = hulk;
}
public class Avengers {
@Autowired
private IronMan iman; // filed 주입
@Autowired
public Avengers(@Qualifier("ironMan") IronMan iman, Hulk hulk) { // 생성자 주입
this.iman = iman;
this.hulk = hulk;
}
@Autowired
public void setHulkBuster(HulkBuster hb) { // setter 주입
this.hb = hb;
}
}