스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트로, 자바 객체의 '생명 주기'를 관리하며, 생성된 자바 객체들에게 추가적인 기능을 제공한다. 스프링에서는 스프링컨테이너에 등록된 자바 객체를 스프링 빈(Bean)이라 한다.
스프링 컨테이너의 종류
- 스프링 컨테이너는 빈(Bean)의 인스턴스화, 구성, 전체 생명 주기 및 제거까지 관리한다. 개발자가 정의한 빈을 객체로 만들어 관리하고 개발자가 필요로 할 때 제공(주입)한다.
- 스프링 컨테이너는 Beanfactory와 ApplicationContext 두 종류의 인터페이스로 구현되어 있다.
BeanFactory
빈 팩토리(BeanFactory)는 스프링 컨테이너의 최상위 인터페이스이다.
BeanFactory는 빈을 등록, 생성, 조회 등의 빈을 관리하는 역할을 하며, getBean() 메서드를 통해 빈을 인스턴스화 할 수 있다.
ApplicationContext
애플리케이션 컨텍스트(ApplicationContext)는 BeanFactory의 기능을 상속받아 제공한다. BeanFactory가 제공하는 기능 외의 부가 기능을 제공한다.
- MessageSource : 메시지 다국화를 위한 인터페이스
- EnvironmentCapable : 개발, 운영, 환경변수 등으로 나누어 처리하고, 애플리케이션 구동 시 필요한 정보들을 관리하기 위한 인터페이스
- ApplicationEventPublisher : 이벤트 관련 기능을 제공하는 인터페이스
- ResourceLoader : 파일, 클래스 패스, 외부 등 리소스를 편리하게 조회
스프링 컨테이너의 기능
스프링 빈(Bean)의 인스턴스화, 구성, 전체 생명 주기 및 제거까지 관리한다.
스프링 컨테이너를 통해 새로운 객체를 생성하지 않고(싱클톤) 필요한 만큼의 많은 객체를 가질 수 있다.
의존성 주입(DI)을 통해 애플리케이션의 컴포넌트를 관리할 수 있다.
스프링 컨테이너는 서로 다른 빈을 연결하여 애플리케이션 빈을 연결하는 역할을 한다.
개발자는 모듈 간에 의존 및 결합으로 인해 발생하는 문제로부터 자유로울 수 있다.
스프링 컨테이너를 사용하는 이유
객체를 사용하기위해서는 new명령어를 통해 객체를 생성하게되는데, 그로 인해 애플리케이션에서는 수많은 객체가 존재하고 서로를 참조하게 된다. 이렇게 되면 참조가 많으면 많을수록 의존성이 높아지게 된다.
또한, 프로젝트가 커질수록 의존도는 높아지게되고, 그에 따라 부모 코드의 변경으로 자식객체에는 잦은 에러를 유발할수 있다.
OOP에서는 낮은 결합도와 높은 캡슐화와 강한 응집도를 지향하기에, 객체 간의 의존성을 낮추어(느슨한 결합) 결합도는 낮추고, 높은 캡슐화 (응집도) 를 위해 스프링 컨테이너가 사용된다.
스프링컨테이너에 Bean을 등록하는 방법
Spring Bean을 등록하는 방법은 주로 다음과 같은 'XML 기반 설정'과 '자바 기반 설정'과 '컴포넌트 스캔'을 사용하는 방법등 다양하게 사용되고 있다.
1.XML 기반 설정을 통한 Bean 등록
xml파일(application-config.xml)을 만들어서 XML문법에따라서 Bean을 등록할수 있다.
- 먼저 프로젝트를 하나 만든다.(sampleBean프로젝트)
ㆍ java버젼 : 11 , spring버젼 : 4.3.14 , maven compiler 버전 : 자바버젼과 맞춰준다.
- src/main/resources 패키지에 하위 패키지를 만든다.
ㆍ 패키지명은 xml
- xml패키지아래 'bean configuration'파일을 하나 만들어준다.(아래 새파일을 만드는 두가지 방법중 어느것을 사용해도 좋다. 모두 해당 폴더(xml)에서 아래쪽으로 만들수있도록 작업해야 한다.)
Bean의 이름은 'application-config.xml' 로 지정한다.
앞의 그림처럼 'beans'가 등록되어 있어야 한다. 만약 없다면, 아래쪽의 'Namespaces'탭을 클릭후 'beans'를 체크한후 다시 'Source'탭을 클릭해서 확인할수 있다.
- 빈으로 등록할 java파일을 만들어준다. 여기서는 'SampleController.java'와 'SampleService.java' 두개의 클래스를 스프링빈으로 등록시켜보자.(먼저, 패키지 'controller' 과 'service' 를 만들어준다.(HomeController.java는 controller패키지로 옮겨준다.)
- SampleController.java 만들기(controller패키지에 만든다)
- SampleService.java 만들기(service패키지에 만든다)
앞에서 만든 'SampleController.java'파일과 'SampleService.java'파일을 '스프링 컨테이너'에 '스프링 빈'으로 등록시켜주기 위하여 'application-config.xml'파일에 아래와 같이 입력한다.
- 'application-config.xml'
- 앞의 코드로 'SampleController.java'파일과 'SampleService.java'파일은 '스프링 컨테이너'에 '스프링 빈'으로 등록되게 된다.
이제는 등록된 빈을 main클래스에서 연결(호출)시켜보도록 하자.
- 테스트를 위해 'bean'패키지를 하나 더 만들어준다. 그리고 그 안에 'SampleBeanMain.java' 클래스를 만들어준다.(main메소드 추가해준다)
- 'SampleBeanMain.java'파일에 XML파일을 자바클래스와 연결해주기위한 코드를 작성해준다.
앞의 코드중에서 '스프링컨테이너'에 등록시킨 'Bean'을 'Java로 불러오는 방법'?
- xml파일을 읽어오는 위치와 시점에 따른 4가지 Class
ㆍClassPathXmlApplicationContext : ClassPath에 위치한 xml 파일을 읽어 설정 정보를 로딩, root로부터 경로를 지정함
ㆍFileSystemXmlApplicationContext : 파일 경로로 지정된 곳의 xml을 읽어 설정 정보를 로딩
ㆍXmlWebApplicationContext : 웹 어플리케이션에 위치한 곳에서 xml파일을 읽어 설정 정보를 로딩(XML 설정 파일을 불러와 웹 기반의 스프링 애플리케이션을 개발할 때 사용하는 컨테이너)
ㆍAnnotationConfigApplicationContext : @Configuration 어노테이션이 붙은 클래스를 이용하여 설정 정보로 로딩(자바 설정 파일 형태로 불러와 웹 기반의 스프링 애플리케이션을 개발할 때 사용하는 컨테이너)
앞에 정의된것들을 보편화 시켜서 만들어놓은 클래스 : GenericXmlApplicationContext() - 파일 시스템이나 클래스 경로에 있는 XML 파일을 로딩하여 구동하는 컨테이너
- xml로 만든 파일을 스프링컨테이너에 bean으로 등록시켰으면, 호출시는 'getBean("id") 또는 getBean("id", 클래스)'로 불러서 사용한다. 여기서 id는 xml에서 bean으로 등록한 클래스의 id를 말한다.
(사용예)
① ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("xml/application-config.xml");
② ApplicationContext ctx = new ClassPathXmlApplicationContext("xml/application-config.xml");
③ ApplicationContext ctx = new GenericXmlApplicationContext("xml/application-config.xml");
④ AbstractApplicationContext ctx = new GenericXmlApplicationContext("xml/application-config.xml");
(추가 예제)
- 테스트를 위해 외부(main클래스)에서 컨트롤러로 '성명'을 넘기면 컨트롤러는 서비스객체에서 값을 편집해서 다시 받아서 콘솔에 출력하는 메소드를 추가로 만들어보자.
추가코드부분은 아래와 같다.
- SampleController.java(생성자를 통한 값을 주입하기위해 서비스객체를 필드로선언하고 기본생성자에 매개변수로 할당시켜 초기화 시켜주고 있다. - 주석으로 표시한곳은 setter를 통한 값을 주입하기위해 작성한 부분이다.) - 참고로 생성자로 주입하게되면 필드에 'final'을 붙여줄수 있으며 이렇게 되면 처음 생성시에만 값을 부여하기에 중간에 값을 변경시킬수 없도록 하기에 보안에 강하다.(setter로 할경우는 final 키워드는 생략한다)
앞의 컨트롤러를 보면 helloPrint()메소드는 외부로부터 '성명'을 받아서 서비스객체를 통해서 값을 처리후 돌려받아서 출력시켜주는 코드이다.
- SampleService.java 파일의 sayHello()메소드
컨트롤러에서 생성자(또는 setter)로 값을 주입하여 서비스객체에서 처리하기에 xml파일(application-config.xml)에서 컨트롤러 생성시에 서비스객체를 참조객체로 주입(DI - Dependency Injection)시켜줘야 한다.
- application-config.xml(기본은 생성자로 주입한경우이고, 주석처리된것은 setter로 주입한경우이다)
이제 main클래스에서 컨트롤러 호출시 '성명'을 넘겨주어서 컨트롤러에서 콘솔에 값을 찍는지 확인해 본다.
- SampleBeanMain.java(실행 클래스)
실행시킨 결과는 아래와 같다.
앞의 결과를 보면 생성되어보이는 두객체는 서로 같은 객체임을 알수 있다. 즉, 스프링은 기본적으로 스프링컨테이너에 빈을 등록시에 싱글톤 패턴형식으로 객체를 등록시켜두기에 해당 객체를 호출하게되면 모두 같은 객체를 사용하고 있음을 알수 있다.
만약, 다른 인스턴스로 생성해서 사용하고자 한다면, application-config.xml파일에서 '스프링컨테이너'에 '빈'을 등록할때 scope="prototype" 옵션을 붙여주면된다. 아래 그림을 참조한다.
다시 main클래스를 실행시킨후 결과를 확인해본다.
서로 다른객체로 비교되고 있음을 확인할수 있다.
2. 자바 기반 설정 (Java Config)
Spring 3부터는 XML 설정 대신 자바 기반 설정을 사용하는 방식이 더 선호되고 있다. 사용되는 어노테이션은 @Configuration과 @Bean 애노테이션을 사용해 Bean을 등록할 수 있다.
어노테이션 기반으로 만들기위해서 앞의 예제에서 만들어진 'application-config.xml' 파일을 'application-config.xml_'로 이름 변경시켜두고, com.spring.sampleBean.bean패키지아래 아래와 같은 스프링 환경설정 클래스(AppConfig.java)를 만들어준다.
- AppConfig.java 파일의 내용은 아래와 같다.
앞의 코드를 보면 '스프링 컨테이너'에 빈을 등록하는 환경 클래스파일의 상단에는 '@Configuration' 을 붙여주고, 등록시킬 객체 상단에는 '@Bean'어노테이션을 붙여준다. 이때 컨트롤러는 생성시에 서비스객체를 매개값으로 할당시켜주고 있다.
스프링 빈으로 등록을 마쳤기에 main클래스에서 실행할수 있도록 소스코드를 바꿔준다. 아래 코드는 기존 코드를 모두 주석처리후 환경파일을 생성후 값을 주입시켜주고 있다.
- SampleBeanMain.java
실행결과는 아래와 같다.
3. 컴포넌트 스캔을 이용한 자동 등록 (Component Scan)
컴포넌트 스캔을 사용하면 @Component, @Service, @Repository, @Controller 등의 애노테이션을 사용하여 자동으로 Bean을 등록할 수 있다.
이번에는 기존의 'AppConfig.java' 파일의 내용을 모두 주석처리하고 상단에 @ComponentScan() 어노테이션을 붙여준다.
AppConfig.java 안의 소스코드는 모두 주석처리했다. 그리고 아래와 같이 클래스명 상단에 다음 코드를 추가했다.
- 기존에 실습하던 SampleBeanMain.java의 내용들을 모두 주석처리한다.
앞의 사진과 같이 'AppConfig.java', 'SampleBeanMain.java'파일의 클래스안의 내용을 모두 주석처리하고, 사용할 클래스(SampleController.java / SampleService.java)들을 스프링빈으로 등록시킬수 있도록 준비하자.
- 먼저 SampleController.java 파일은 컨트롤러로 등록시켜준다.
SampleController.java 파일
- 다음은 SimpleService.java 파일을 스프링 Bean으로 등록시켜주기위해 클래스 상단에 @Component 어노테이션을 붙여준다.
이렇게 클래스상단에, @Component 애노테이션을 클래스에 붙이면 Spring이 이 클래스를 자동으로 Bean으로 등록한다. 이때 @Component 대신 @Service, @Repository, @Controller 등을 사용할 수 있다.
이제 웹을 통해서 실행을 시켜주기위해서 SampleController.java 에 'helloPrint()'메소드를 호출할수 있도록 매핑주소(@GetMapping())를 붙여준다. 아래 수정된 코드이다.
- SampleController.jva 파일 수정본
앞의 코드를 실행시키기위해서는 웹을 통해서 url 매핑시켜줘야 한다.
아래와 같이 서버를 실행시켜주자.
실행된 브라우저 주소창에 아래와 같이 입력시켜서 실행시켜준다.
콘솔에 출력된 결과를 확인하면된다.
이상으로 스프링컨테이너에 스프링빈을 등록하는 방법과 예제를 만들어봤다.
'프로그래밍언어 > Springframework' 카테고리의 다른 글
스프링 AOP(Aspect Oriented Programming) (10) | 2024.11.15 |
---|
댓글