자바에서 Annotation(@)은 코드 사이에 주석처럼 쓰이며 특별한 의미, 기능을 수행하도록 하는 기술이다.
수업때 2가지 경우를 실습해보았는데 2가지 경우에서 사용한 어노테이션을 위주로 복습하면서 작성하였다.
어노테이션의 종류는 훨씬 다양하다고 하니 기본부터 익히고 차차 다른 종류도 공부해봐야 할 것 같다.
1. @Configuration & @Bean
@Configuration //클래스를 스프링 설정 클래스로 지정하고 스프링 빈으로 등록을 하겠다.
public class BeanFactory {
@Bean
public Person createPerson() {
Person p2 = new Person();
p2.setName("유재석");
Food myfood = new Chicken();
p2.setMyFood(myfood);
return p2;
}
@Bean
public Person createPerson2() {
Food myFood = new Chicken();
return new Person("로운", myFood);
}
}
@Configuration을 클래스에 적용하고 @Bean을 해당 Class의 method에 적용하면 @Autowired로 Bean을 주입받아 사용할 수 있다.
1. @Configuration
1) 클래스를 스프링 설정 클래스로 지정하고 스프링 빈으로 등록을 하겠다는 의미이다.
2) 해당 클래스에서 1개 이상의 Bean을 생성하고 있음을 명시하고 있다. 그렇기 때문에 @Bean 어노테이션을 사용하는 클래스의 경우 반드시 @Configuration과 함께 사용해주어야 한다. @Configuration을 사용하지 않고 @Bean만 사용하여도 bean으로 등록되기는 하지만 싱글톤은 보장하지 못한다.
3) 빈의 설정을 담당하는 @Configuration 어노테이션도 내부적으로 @Component를 가지고 있어 @Configuration이 붙은 클래스도 Spring의 빈으로 등록된다.
2. Bean
1) @Configuration 어노테이션이 명시된 클래스 내에 들어가는 메소드에서 선언한다.
2) 같은 클래스 타입으로 여러 개의 빈을 등록할 수 있다.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/* 어노테이션을 활용한 객체 의존성 주입
* 어노테이션이 붙은 클래스를 탐색해서 컨테이너에 자동으로 등록(컴포넌트 스캔)
*
* @Component(클래스), @Bean(메소드, @Configuration)
*
* */
AbstractApplicationContext cntx = new AnnotationConfigApplicationContext(BeanFactory.class);
Person p = (Person)cntx.getBean("createPerson");
p.getMyFood().eat("태리");
System.out.println(p);
Person p2 = (Person)cntx.getBean("createPerson2");
p2.getMyFood().eat("후라이드");
System.out.println(p2);
}
AnnotationConfigApplicationContext() 는 ApplicationContext 구현체는 인풋으로 @Configuration 클래스뿐만 아니라 평범한 @Component 클래스와 JSR-330 메타데이터로 어노테이션이 붙은 클래스들도 받아들일 수 있다. 컴포넌트 스캔 기능을 통해 XML을 사용하지 않고 스프링 컨테이너를 사용할 수 있다.
AnnotationConfigApplicationContext() 객체인 cntx를 생성하여 getBean()을 이용해 BeanFactory 클래스에서 @Bean을 통해 빈으로 등록된 "createPerson", "createPerson2"을 가져온다.
BeanFactory 의 "createPerson()"과 "createPerson2()"메소드는 앞의 코드에서 각각 setter와 생성자를 통해 value값인 name과 new연산자로 생성한 myFood객체를 주입받았다.
2. @Component & @Autowired @ @Qualifier("name")
@Component
public class Person2 {
@Value("유야호")
private String name;
//스프링이 자동으로 의존하는 객체 주입해준다.
@Autowired
@Qualifier("pizza")
private Food myFood;
public Person2() {
// TODO Auto-generated constructor stub
}
public Person2(String name, Food myFood) {
super();
this.name = name;
this.myFood = myFood;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Food getMyFood() {
return myFood;
}
public void setMyFood(Food myFood) {
this.myFood = myFood;
}
@Override
public String toString() {
return name + " ~~ " + myFood;
}
}
1. @Component
개발자가 직접 작성한 Class를 Bean으로 등록하기 위한 Annotation이다.
객체를 나타내는 일반적인 타입으로 <Bean>태그와 동일한 역할을 한다.
Component에 대한 추가 정보가 없다면 Class의 이름을 낙타표기법으로 변경한 것이 Bean id로 사용된다.
하지만 @Bean과 다르게 @Component는 name이 아닌 value를 이용해 Bean의 이름을 지정한다.
2. @Autowired
필드변수, setter method, constructor(생성자)에서 사용하며 스프링이 Type에 따라 알아서 Bean을 주입해준다.
<property> , <constructor-arg> 태그와 동일한 역할을 한다.
Controller 클래스에서 DAO나 Service에 관한 객체들을 주입 시킬 때 많이 사용한다.
3. @Qualifier("name")
주입하고자 하는 객체가 여러 개 있을 경우 @Qualifier("name")을 통해 원하는 객체를 지정하여 주입할 수 있다.
@Autowired 어노테이션과 같이 사용된다.
위의 코드에서 @Autowired를 하면 spring은 type이 Food로 등록된 bean을 찾아서 setter와 생성자에 주입시켜줘야 한다.
@Component 어노테이션으로 등록된 Food인터페이스 구현체는 아래 코드에서 볼 수 있는 것처럼 2개이다. 이때 2개 중 어떤 빈을 우선으로 사용해야 할지 명시를 해주지 않으면 스프링이 찾지 못할 것이다.
이때 2가지 방법으로 스프링에게 우선적으로 주입할 빈을 알려줄 수 있다.
첫 번째 방법은 아래 코드에서 볼 수 있는 것과 같이 @Primary 어노테이션을 이용하는 것이다. @Primary 가 적힌 클래스가 있다면 그 타입의 객체가 우선으로 주입된다.
두 번째 방법은 @Qualifier() 어노테이션을 사용하여 원하는 객체를 주입시켜 줄 수 있다. 위 코드에서처럼@Qualifier("pizza") 로 @Autowired 아래에 적어주면 이름이 pizza인 bean을 주입시킨다. chicken 클래스에 @Primary가 적혀 있다하더라도 @Qualifier() 가 우선되며, Qualifier에 적힌 이름이 @Component로 등록되지 않았어도 클래스 이름을 camelCase로 하여 자동으로 찾아서 주입시켜 준다.
4. @Value
단순한 값을 주입할 때 사용되는 어노테이션이다.
@Value(“Spring”)은 <property .. value=“Spring”/>와 동일한 역할을한다.
@Primary
@Component
public class Chicken implements Food {
@Override
public void eat(String foodName) {
System.out.println("집에서 " + foodName + "치킨을 먹는 중!!");
}
}
@Component
public class Pizza implements Food {
@Override
public void eat(String foodName) {
System.out.println("한강에서 " + foodName + "피자를 먹는 중!!");
}
}
출처 및 참고 : https://mangkyu.tistory.com/75 [MangKyu's Diary]
https://glory-day.tistory.com/104
https://blog.outsider.ne.kr/785
https://dog-developers.tistory.com/16
'spring' 카테고리의 다른 글
[spring] DispatcherServlet (0) | 2021.10.23 |
---|---|
[spring] Context란? (0) | 2021.10.20 |
[spring] 느슨한 결합력과 인터페이스(DI 이해에 도움) (0) | 2021.10.15 |
[spring] AOP (0) | 2021.10.15 |
[spring] DI, IOC란? (0) | 2021.10.14 |