[Spring] @Component 애노테이션 및 함께 사용하는 애노테이션 정리

2021. 4. 22. 01:26 Spring Framework/Spring Core

 

[Spring] @Component 애노테이션 및 함께 사용하는 애노테이션 정리

스프링 빈 설정 XML 파일에 <bean id="..." class="..."/>나 자바 @Configuration 클래스에서 @Bean을 붙여 빈을 등록하던 것처럼 빈 클래스에 @Component 애노테이션을 붙여 빈을 등록할 수 있다.

즉 @Component를 사용해서 빈 설정 파일이 아니라 빈 클래스에서 빈을 직접 등록할 수 있다.

 

Component Scan 설정

@Component를 붙인 클래스를 스캔할 수 있도록 설정해 주어야 한다.

 

1) XML 설정을 사용할 경우

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd">
                        
    <!-- 지정된 패키지 안에 있는 Bean 클래스들의 어노테이션을 분석하도록 지정한다 -->
    <context:component-scan base-package="com.atoz_develop.beans1"/>
    <context:component-scan base-package="com.atoz_develop.beans2"/>
</beans>

 

<context:component-scan> 태그의 base-package에 스캔할 패키지를 설정한다.

패키지가 여러개인 경우 <context:component-scan>를 여러개 작성할 수 있다.

 

2) @Configuration 설정을 사용할 경우

@Configuration
// 지정된 패키지의 Bean 클래스들의 어노테이션을 분석하여 Bean을 등록하라고 지정한다.
@ComponentScan(basePackages = {"com.atoz_develop.beans", "com.atoz_develop.bean1"})
@ComponentScan(basePackages = "com.atoz_develop.beans2")
@ComponentScan(basePackages = "com.atoz_develop.beans3")

public class BeanConfigClass { }

@Configuration 클래스를 사용할 경우 @ComponentScan 애노테이션의 basePackages를 사용해서 패키지를 설정한다.

패키지가 여러개일 경우 배열로 지정하던지, @ComponentScan을 여러개 붙이는 방법을 사용할 수 있다.

 

@Component

@Component
public class TestBean { }

이는 <Bean class=“…”/>와 동일한 표현이다.

 

1) @Component로 등록한 빈 가져오기

ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanConfigClass.class);

TestBean1 t1 = ctx.getBean(TestBean1.class);
TestBean1 t1 = (TestBean1) ctx.getBean("testBean1");
TestBean1 t1 = ctx.getBean("testBean1", TestBean1.class);

@Component를 붙여 빈을 등록하면 클래스 이름의 첫 문자를 소문자로 바꾼 것이 빈의 이름(id)이 된다.

 객체가 생성되는 시점은 ApplicationContext 객체가 생성되는 시점이며 기본적으로 singleton scope이다.

 

2) @Component("이름")

@Component("tb")
public class TestBean { }

@Component("이름")과 같이 빈 이름(id)를 지정할 수 있다.

 

@Lazy

@Component
@Lazy
public class TestBean { }

@Component를 붙여서 등록한 빈은 기본적으로 ApplicationContext 객체가 생성될때 빈 객체가 생성되는데 @Lazy를 같이 붙이면 getBean()과 같이 해당 빈이 사용될때 빈 객체가 생성된다.

<Bean lazy-init="true"/>와 동일한 표현이다.

 

@Scope

@Component
@Scope("prototype")
public class TestBean { }

@Component를 붙여서 등록한 빈은 기본적으로 singleton scope이 되는데 @Scope를 붙여서 빈의 scope를 설정할 수 있다.

<Bean>의 scope 속성과 동일한 설정을 할 수 있다.

 

@PostConstruct, @PreDestroy

@Component
public class TestBean {

    @PostConstruct
    public void init() {
        System.out.println("init 메서드 호출");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("destroy 메서드 호출");
    }
}

@PostConstruct로 빈 생성자 호출 이후 자동으로 호출될 메서드와 @PreDestroy로 빈 객체가 소멸될 때 자동으로 호출되는 메서드를 등록한다.

자바에서 제공하는 JSR-250 애노테이션이며 사용하려면 다음 라이브러리를 추가해야한다.

 
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

 

자동 주입

@Component로 등록한 빈의 자동 주입 방법은 @Bean으로 등록한 빈의 자동 주입 방법과 동일하다.

@Autowired, @Qualifier, @Resource를 사용할 수 있다.

 

1) @Autowired

@Component
public class TestBean1 {
	
	@Autowired
	private DataBean1 data1;
}

@Component
public class DataBean1 { }

@Autowired는 같은 타입의 빈을 자동 주입하며 필드에 붙이면 해당 필드의 setter가 자동으로 생성된다.

 

2) @Qualifier

@Component
public class TestBean1 {
	
	@Autowired
	@Qualifier("obj2")
	private DataBean2 data2;
}

@Component("obj2")
public class DataBean2 { }

@Autowired와 @Qualifier를 함께 사용하면 @Qualifier에 지정된 이름과 같은 이름의 빈을 찾아 자동 주입된다.

 

3) @Resource

@Component
public class TestBean1 {

	@Resource(name = "obj3")
	private DataBean3 data3;
	
	@Resource(name = "obj4")
	private DataBean3 data4;
	
	@Resource(name = "obj5")
	private DataBean3 data5;
}

@Component("obj2")
public class DataBean2 { }

@Configuration
@ComponentScan(basePackages = "com.atoz_develop.beans")
public class BeanConfigClass {
	
	@Bean
	public DataBean3 obj4() {
		return new DataBean3();
	}
	
	@Bean
	public DataBean3 obj5() {
		return new DataBean3();
	}
}

JSR-250 애노테이션 @Resource는 필드명과 이름이 같은 빈을 찾아 자동 주입한다.

@Resource(name = 이름)과 같이 특정 이름을 지정하면 필드명이 아닌 지정한 이름의 빈을 찾아 자동 주입한다.

사용하려면 JSR-250 애노테이션 라이브러리를 추가해야 한다.

 

4) 생성자 자동 주입

@Component
public class TestBean3 {
	
	private DataBean4 data3;
	private DataBean5 data4;
	
	public TestBean3(DataBean4 data3, DataBean5 data4) {
		this.data3 = data3;
		this.data4 = data4;
	}
}

@Component
public class DataBean4 { }

@Component
public class DataBean4 { }

@Component를 붙여 등록한 빈은 생성자 아규먼트와 타입이 같은 빈이 자동으로 주입된다.

이러한 생성자 자동 주입 방법은 스프링 5.1부터 deprecated된 @Required의 개선된 대체 방법이다.

즉 빈에서 반드시 주입해야하는 필드는 생성자 주입 방법을 사용한다.

 

5) @Value

@Component
public class TestBean3 {
	
	private int data1;
	private String data2;
	private DataBean4 data3;
	private DataBean5 data4;
	
	public TestBean3(@Value("100") int data1, @Value("문자열") String data2, DataBean4 data3, DataBean5 data4) {
		this.data1 = data1;
		this.data2 = data2;
		this.data3 = data3;
		this.data4 = data4;
	}
}

 생성자 아규먼트 중 기본 타입과 문자열 타입은 @Value를 사용해 주입할 값을 직접 지정한다.

 

출처 : atoz-develop.tistory.com/entry/Spring-Component-%EC%95%A0%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EB%B0%8F-%ED%95%A8%EA%BB%98-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%95%A0%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EC%A0%95%EB%A6%AC?category=869243