Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

쉽지않은 블로그

[Spring] Bean 이란? 본문

개발공부/스프링

[Spring] Bean 이란?

쉽지않네 2021. 4. 18. 23:20

스프링 컨테이너의 역할

느슨한 결합을 해결하기 위해서 IoC 컨테이너를 사용하여

객체를 나의 코드(명확히 말하면 내가 구현한 클래스)가 직접 관리(생성)하는 것이 아니라

모든 관리의 주체를 스프링 프레임워크에게 부여(역전) 시켜 inversion of Control을 가능케 한다고 배웠었다

 

굳이 이렇게 역전을 시키는 이유에 대해서는 다음 글을 참고하면 좋을 것 같다.

dutchcoffee.tistory.com/27

 

[Spring] DI & IOC (1) 느슨한 결합력

자바의 객체지향 프로그래밍 관점에서 보게 되면 1) 클래스가 다른 클래스를 사용하거나 2) 클래스가 다른 클래스를 상속하거나  등 어떤 클래스 객체가 하는 일이 다른 객체에 영향을 받게 되

dutchcoffee.tistory.com

또한 싱글톤 패턴이라 불리는 

( 어느 곳에서 호출하여도 해당 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴)

것 을 보장해 주어야 느슨한 결합으로 이루어진 코드에 안정성을 부여할 수 있을 것이다.

 


Bean 이란? 

스프링 프레임워크 내부에는 DI , IOC , 싱글톤 패턴 등을 쉽게 해결해주는 스프링 만의 객체 처리 방식이 존재하는데

이때 스프링 프레임워크가 관리하는 객체들을 Bean이라고 부르게 된다

 

"객체"라는 것에 대한 명칭에 대한 혼란을 줄이기 위해서

스프링 프레임워크가 관리하는 객체를 Bean이라고 하고

스프링 프레임워크가 관리하지 않는 그냥 클래스 객체는 POJO (Plain Old Java Object)라고 부르기도 한다.

 

new 키워드를 사용하여 생성하는 객체는 절대 Bean 이 될수 없다.

 

자 그러면 스프링 프레임워크와 관련된 라이브러리를 받아놓았다고 해서

내가 객체(클래스)를 정의하면 모든 객체(클래스)가 Bean으로 인식되는 것일까?

 

아니다 

스프링 프레임워크에게 특정 객체를 Bean으로 관리해달라고 명시해줄 필요가 있다.


Bean 으로 선언하는 방법

명시해주는 방법에는 대표적으로 두 가지가 있다

 

1.@Bean과 @Configuration을 사용하는 방법

//AppConfig.java

@Configuration     //현재 파일이 Config (빈 설정파일이라는것을 명시)
public class AppConfig {

    @Bean // Bean 을 등록하는 어노테이션 , 아무것도 없을 경우 Bean 의 이름은 메소드이름 carService 가 된다.
    public CarService carService(){
        return new CarServiceImpl(engineService());
    }
   
	@Bean
	public EngineService engineService(){
		return new EngineBMW();
	}
}

설정 파일로 지정할 클래스 (보통 **Config로 이름을 작명한다)를 지정해주고

그 안에 Bean으로 사용할 클래스들을 선언한다.

객체지향의 유연함을 위해 인터페이스를 반환하는 클래스들을 사용한다.

engineA와 같이 변경될 수 있는 부분만 따로 주입 인자로 관리해준다.

 

 

해당 방식을 수동방식이라고 하는데 

수동 방식은 잘 추천되지 않는다

비즈니스 로직이 아닌 개발하고 확인할 용도로 사용될 객체들만 Bean을 이용하여 선언해준다.

 

2.@Component를 사용하는 방법

AppConfig.java
@Configuration     //현재 파일이 Config (빈 설정파일이라는것을 명시)
@ComponentScan    //현재 AppConfig.java 파일이 존재하는 디렉토리 포함 하위 모든 Component들을  스캔하여 spring bean 으로 등록한다
// basePackages 설정을 통해서 읽어올 패키지 범주를 명시할수도 있다.
public class AppConfig { 
	//비어 있어도 괜찮다
}

******************************************
CarserviceImpl.java
@Component
public class CarServiceImpl implements CarService{
	...
	...
}

******************************************
EngineBMW.java
@Component
public class EngineBMW implements EngineService{
	...
	...
}

Component 스캔을 이용하면

AppConfig에 모든 bean 이름 정보와 클래스 정보를 표현하지 않고

클래스 정의와 동시에 bean으로 등록할 수 있는 방법을 제공한다

 

하지만 위와 같이 Component 스캔을 이용하면 한 가지 해결해야 될 문제가 있을 것이다

 

아까 @Bean을 사용하는 방식에서는 CarServiceImple 생성자 메서드에 BMW 엔진의 생성자가 들어가 있는 구조여서 문제가 되지 않았지만

 

@ComponentScan 방식에서는

CarServiceImpl 이 BMW 엔진을 장착해야 된다는 점을 어떻게 알 수 있을까??

 => CarServiceImpl 도 스프링이 관리하고 BMW 엔진도 스프링이 관리한다.  CarServiceImpl 이 BMW 엔진을 사용한다는 의존관계 주입이 필요하다

 

 


Bean을 조회하는 방법

스프링 컨테이너에서 내가 등록한 Bean을 뽑아내는 방법은

내가 load 한 스프링 컨테이너의 getBean 메서드를 사용하여 뽑으면 된다.

ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); 
//AppConfig 파일에 Bean으로 등록해야될 객체들을 적어놓았으니 컨테이너에 load 해줘

CarService carService = ac.getBean("carService",CarServiceImpl.class);
// "이름" , 과 클래스.class 를 이용하여 검색하는 방법
// 이름이 중복된 Bean 은 존재하면 안된다.



CarService carService = ac.getBean(CarServiceImpl.class);
CarService carService = ac.getBean(CarService.class);
//이름 없이 반환 클래스를 보고 가져오는 방법
//구현체를 명시해도 ok
//인터페이스를 명시해도 ok

//! 다만 동일한 인터페이스 반환 Bean 일경우 
//명확한 구현체 이름이나 이름을 통하여 검색해야한다

 

이름과 반환 클래스 타입을 이용하여 검색할 수 있다.

이때 Bean 끼리 중복된 이름을 가져선 안된다. (애초에 그렇게 등록하면 안 된다)

 

만약 반환 타입만을 이용하여 검색할 경우

타입이 중복되지 않게끔 (인터페이스 또는 구현체)를 검색 클래스로 사용해야 한다.

 

참고문헌  : 

www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8#

Comments