본문 바로가기

Framework/Spring

[Spring] 08. 빈(Bean) 설정하기

빈 (Bean)

 

Bean은 스프링 컨테이너에 의해 관리되는 객체이다.

개발자가 빈을 직접 생성하거나 관리하는 것이 아니라, 스프링 IoC 컨테이너에 의해 생성되고 관리된다.

 

빈은 XML 설정 파일, Java 설정 파일, Annotation 등을 통해 설정할 수 있다.

  XML 기반 Java 기반 Annotation 기반
특징 XML 파일 사용 Java 코드 사용 Annotation 사용
장점 분리된 설정 파일
표준화된 포맷
레거시 지원
타입 안정성
IDE 지원
가독성 및 유연성
자동화
직관적
컨벤션 기반
단점 가독성 저하
타입 안정성 부족
IDE 지원 제한
초기 학습 곡선
복잡성 증가
설정 코드 증가
설정의 분산
제어 어려움
테스트 어려움

 

 

 

XML 설정 파일을 사용한 Bean 설정

 

XML 파일을 사용하여 Bean을 설정하는 방식은 스프링의 초기 버전부터 사용된 전통적인 설정 방식이다.

// Car.java

public class Car {
    private Engine engine;

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        engine.start();
        System.out.println("Car is driving");
    }
}
// Engine.java

public class Engine {
    public void start() {
        System.out.println("Engine started");
    }
}







 

<bean> 태그는 하나의 빈(Bean)을 정의하는 태그이다.
id 빈의 이름 지정하여 다른 빈에서 해당 빈을 참조할 때 사용
class 스프링 컨테이너가 해당 빈을 생성할 때 사용할 클래스의 경로 설정
<property> 태그는 해당 빈(Bean)의 속성을 정의하는 태그이다.
name 참조할 프로포티 이름 설정
ref 참조할 빈 설정
// applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    // id가 engine이고, class가 com.multi.spring2_2.xml_test.Engine인 빈 정의
    <bean id="engine" class="com.multi.spring2_2.xml_test.Engine"/>

    // id가 car이고, class가 com.multi.spring2_2.xml_test.Car인 빈 정의
    <bean id="car" class="com.multi.spring2_2.xml_test.Car">
    
        // Car 클래스의 engine이라는 속성 설정
        // engine이라는 이름을 가진 빈을 참조하여 Car 객체의 engine 속성에 주입
        <property name="engine" ref="engine"/>
    </bean>

</beans>
1. 빈 생성
    -  스프링 컨테이너는 XML 설정 파일에 정의된 내용을 바탕으로 Engine 클래스의 인스턴스 생성
    -  이 인스턴스는 engine 이라는 ID로 스프링 컨테이너에서 관리


2. 빈 의존성 주입
    -  Car 클래스의 인스턴스 생성할 때, 스프링 컨테이너는 Car 클래스의 engine이라는 이름의 프로퍼티 찾음
    -  이 프로퍼티에 engine 이라는 ID를 가진 Engine 빈 주입
 
3. 결과
    -  Car 객체는 Engine 객체를 자신의 engine 프로퍼티로 가지게 되어, 두 객체가 서로 연결
    -  이를 통해 Car 클래스와 Engine 클래스는 의존 관계를 가지며, 이 관계는 스프링 컨테이너에 의해 관리

 

// Main.java

public class Main {
    public static void main(String[] args) {
        // ClassPathXmlApplicationContext가 applicationContext.xml 파일을 읽어 스프링 컨테이너 초기화
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        // 스프링 컨테이너에서 car라는 이름의 빈을 Car 클래스 타입으로 가져오기
        Car car = context.getBean("car", Car.class);
        
        // car 객체의 drive() 메서드 호출
        car.drive();
    }
}

 

 

 

Java 코드를 사용한 Bean 설정

 

Java 코드를 사용하여 Bean을 설정하는 방식으로 @Configuration@Bean 어노테이션을 사용한다.

AppConfig.java 애플리케이션의 기본 설정 담당
WebConfig.java Spring MVC 설정을 담당하며 뷰 리졸버를 설정
WebAppInitializer.java 서블릿 컨텍스트 초기화

 

// WebAppInitializer.java

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    public WebAppInitializer(){
        System.out.println("WebAppInitializer created");
    }

    // AppConfig.class 반환하여 루트 컨텍스트 설정 제공
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    // WebConfig.class 반환하여 DispatcherServlet 설정 제공
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }

    // DispatcherServlet의 URL 매핑 정의
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

 

@Configuration 해당 클래스가 스프링의 설정 클래스임을 정의
@ComponentsScan 지정된 패키지 내의 컴포넌트를 검색하고 자동으로 빈으로 등록
// AppConfig.java

// 이 클래스가 스프링의 설정 클래스임을 나타내며, 스프링 빈 정의 포함
@Configuration

// 패키지 내의 클래스를 스캔하여 @Component, @Service, @Repository, @Controller 붙은 클래스를 빈으로 등록
@ComponentScan(basePackages = "com.multi.spring2_2.java_test")
public class AppConfig {
    // 외부 클래스의 빈 객체 설정
}

 

@Configuration 해당 클래스가 스프링의 설정 클래스임을 정의
@EnableWebMvc 스프링 MVC의 기본 설정을 자동으로 적용
@ComponentsScan 지정된 패키지 내의 컴포넌트를 검색하고 자동으로 빈으로 등록
// WebConfig.java

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.multi.spring2_2")
public class WebConfig implements WebMvcConfigurer {

    public WebConfig(){
        System.out.println("WebConfig created");
    }
    
    // 컨트롤러에서 home이라는 뷰 이름 반환하면 이 리졸버는 /WEB-INF/views/home.jsp 파일을 찾아 뷰로 사용
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    // /resources/**로 시작하는 모든 요청이 /resources/ 디렉토리에서 제공
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/resources/");
    }

}

 

 

 

Annotation을 사용한 Bean 설정

 

Annotation을 사용하여 Bean을 설정하는 방식은 @Component, @Service, @Repository, @Controller 을 사용한다.

 

@Component 스프링이 해당 클래스를 빈으로 관리
@Autowired 의존선 주입을 자동으로 처리
// Car.java

// Car 클래스 생성될 때, 해당 클래스를 빈으로 관리
@Component
public class Car {
    private final Engine engine;

    // Car 객체 생성될 때, Engine 객체 자동 주입
    @Autowired
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        engine.start();
        System.out.println("Car is driving");
    }
}
// Engine.java

@Component
public class Engine {
    public void start() {
        System.out.println("Engine started");
    }
}










1. 빈 생성
     -  @Component를 사용하여 Car 클래스가 스프링 컨텍스트에서 빈으로 등록

2. 의존성 주입
     -  @Autowired를 사용하여 Car 클래스가 생성될 때, Engine 타입의 빈이 자동으로 주입
     -  즉, Car 객체가 생성될 때, 스프링 컨텍스트에 있는 Engine 빈을 자동으로 engine 필드에 주입

3. 생성자 호출
     -  스프링은 Car 클래스를 빈으로 등록하기 위해 먼저 Engine 빈을 찾음
     -  Engine 클래스가 빈으로 등록되어 있다면 해당 Engine 객체가 생성되거나 존재하는 Engine 빈 사용
     -  스프링은 Car 클래스의 생성자를 호출하여 Engine 객체를 주입하고 Car 객체 생성

 

// Main.java

public class Main {
    public static void main(String[] args) {
        ApplicationContext context
                = new AnnotationConfigApplicationContext(AppConfig.class);
        Car car = context.getBean(Car.class);
        car.drive();
    }
}