스프링(Spring) 컨테이너
스프링은 객체를 관리하는 컨테이너를 제공, 컨테이너에 객체를 담아두고 필요할때에 컨테이너로부터 객체를 가져와 사용할 수 있도록 하고 있다( 아마도 싱글톤 패턴과 관련이 있는 듯 하다.)
BeanFactory와 ApplicationContext가 컨테이너 역할을 수행하는 인터페이스.
<<Interface>>
BeanFactory
-----------------------
<<Interface>>
ApplicationContext
-----------------------
<<Interface>>
WebApplicationContext
BeanFactory 인터페이스
org.springframwork.beans.factory.BeanFactory 인터페이스는 빈 객체를 관리하고 각 빈 객체간의 의존관계를 설정해주는 기능을 제공하는 가장 단순한 컨테이너. 구현 클래스로는 org.springframework.beans.factory.xml.XmlBeanFactory 클래스가 존재한다. XmlBeanFactory 클래스는 ApplicationContext인터페이스는 구현하지 않았다.
XmlBeanFactory클래스는 외부 자원으로부터 설정 정보를 읽어와 빈 객체를 생성한다. Spring은 org.springframwork.core.io.Resource인터페이스를 사용하여 다양한 종류의 자원을 동일한 방식으로 표현할 수 있도록 하고 있으며, Resource를 이용하여 XmlBeanFactory에 설정 정보를 전달할 수 있다.
Resource resource = new FileSystemResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
AgentService agent = (AgentService)factory.getBean("agent");
Resource구현 클래스
클래스 (org.springframework.core.* or org.springframework.web.*) |
설명 |
FileSystemResource |
파일 시스템의 특정 파일로 부터 정보를 읽어 온다. |
InputStreamResource |
InputStream으로부터 정보를 읽어 온다. |
ClassPathResource |
클래스 패스에 있는 자원으로 부터 정보를 읽어 온다. |
UrlResource |
특정 URL로부터 정보를 읽어 온다. |
ServletContextResource |
웹 어플리케이션의 루트 디렉토리를 기준으로 지정한 경로에 위치한 자원으로 부터 정보를 읽어 온다. |
특정 Resource로부터 설정 정보를 읽어 와 XmlBeanFactory객체를 생성한 뒤에는 getBean() 메서드를 이용하여 알맞은 빈을 가져와 사용하면 된다.
ApplicationContext인터페이스 & WebApplicationContext인터페이스
org.springframework.context.ApplicationContext 인터페이스는 BeanFactory인터페이스를 상속받은 하위 인터페이스로서 BeanFactory가 제공하는 빈 관리 기능이외에 빈 객체 라이프 사이클, 파일과 같은 자원 처리 추상화, 메시지 지원 및 국제화 지원, 이벤트 지원, XML 스키마 확장을 통한 편리한 설정 등 추가적인 기능을 제공하고 있다.
스프링을 이용하여 어플리케이션을 개발할 때에는 단순히 빈 객체 생성 기능만을 제공하는 BeanFactory 보다는 ApplicationContext인터페이스의 구현 클래스를 주로 사용하게 된다.
org.springframework.web.context.WebApplicationContext인터페이스는 웹 어플리케이션을 위한 ApplicationContext로서 하나의 웹 어플리케이션(즉, 하나의 ServletContext)마다 한 개 이상의 WebApplicationContext를 가질 수 있다.
ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, XmlWebApplicationContext가 주요 클래스다.
String configLocation = "config/applicationContext.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
ParserFactory factory = (ParserFactory)context.getBean("parserFactory");
만약 클래스패스에 위치하고 있는 여러 XML파일을 이용하여 ApplicationContext를 생성하고 싶다면, 설정 파일 목록을 담고 있는 String 배열을 ClassPathXmlApplicationContext클래스 생성자에 전달하면 된다.
String[] configLocations = new String[]{"config/applicationContext.xml", "config/aop.xml"};
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
SomeBean bean = context.getBean("beanName");
WebApplicationContext에 대해서는 웹을 할 때 따로 학습 예정 (Spring MVC)
스프링 컨테이너에서 사용될 빈 객체를 생성하고 각 객체 간의 의존 관계를 설정하는 방법.
스프링은 XML파일을 이용한 설정 뿐만 아니라 어노테이션을 이용한 설정도 지원한다. 빈 객체 설정 및 컨테이너를 통한 빈 객체 사용.
<beans ...>
<bean id="carInsDao" class="com.zend4u.Crawler.CarInsDao"></bean>
</beans>
<bean>태그의 class속성은 생성할 빈 객체의 완전한 클래스 이름을 입력하며, id속성은 스프링 컨테이너에서 생성된 객체를 구분하는데 사용 되는 식별 값을 의미한다. id속성 대신 name 속성도 가능하다.
Resource resource = new ClassPathResource("applicationContext.xml");
//스프링 컨테이너 생성
BeanFactory factory = new XmlBeanFactory(resource);
//스프링 컨테이너로부터 빈 객체를 가져와 사용
CarInsDao carInsDao = (CarInsDao)factory.getBean("carInsDao");
getBean()으로 빈을 요청할 때 정의한 xml의 id값을 넣으면 된다. 스프링3 버전 부터 타입변환((CarInsDao) 대신 자바 5의 제네릭(Generic)을 이용해서 원하는 타입으로 빈을 구할 수 있든 getBean()메서드를 제공해주고 있다.
factory.getBean("carInsDao", CarInsDao.class)
<bean>태그를 사용할 때는 <constructor-arg> 태그를 명시하지 않을 경우 기본 생성자가 사용되므로 인자를 갖는 생성자를 정의했다면 기본 생성자도 함께 정의해주어야 한다.
static 메서드를 이용하여 객체를 생성해야하는 경우도 있다. (싱글톤 패턴이 적용된 클래스)
public class ParserFactory {
private static ParserFactory instance = new ParserFactory();
public static ParserFactory getInstance() {
return instance;
}
//기본 생성자 접근 막음
private ParserFactory() {}
...
}
ParserFactory클래스는 생성자를 사용하지 않고 static 메서드인 getInstance() 메서드를 이용하여 ParserFactory객체를 생성하도록 구현. 이런 꼉우는 <bean>태그에 factory-method 속성 값으로 static 메서드를 지정함으로써 해당 메서드를 이용하여 빈을 생성하도록 설정할 수 있다.
<bean id="parserFactory" class="com.zend4u.Crawler" factory-method="getInstance" />
스프링에서 의존관계를 설정하는 방법은 생성자방식, 프로퍼티 설정 방식, 룩업메서드 방식이 있다.
생성자 방식은 의존하는 객체를 생성자를 통해 전달 받는다. 이 경우 <constructor-arg>태그를 이용하여 의존하는 객체를 전달 할 수 있다.
<bean ..>
<constructor-arg>
<ref bean="carInsDao" />
</constructor-arg>
</bean>
만약 전달받는 값이 객체가 아닌 int나 double과 같은 기본 데이터 타입이나 java.lang.String 타입이라면 <ref>태그 대신 <value>태그를 사용하여 값을 지정한다.
<constructor-arg>
<value>10</value>
</constructor-arg>
생성자가 전달받는 파라미터가 2개이상일 경우는 파라미터 개수만큼 <constructor-arg>를 사용하면 된다.
프로퍼티 설정 방식은 setXXX() 형태의 설정 메서드를 사용해서 필요한 객체와 값을 전달 받는 방식.
public void setCarInsDao(CarInsDao carInsDao) {
this.carInsDao = carInsDao;
}
스프링에서는 <property> 태그를 이용, 프로퍼티에 값을 전달 한다.
<bean ...>
<property name="carInsDao">
<ref bean="mysqlCarInsDao" />
</property>
</bean>
<ref>태그를 이용하여 빈 객체를 프로퍼티 값을 전달할 수 있다. 또한 value속성도 이용할 수 있다.
룩업 메서드 인젝션 방식은 필요한 객체를 제공하는 룩업(look up) 메서드를 구현하는 방식이다.
public abstract class Processor {
public void process(String commandName) {
CommandFactory factory = getCommandFactory();
Command command = factory.createCommand(commandName);
command.execute();
}
protected abstract CommandFactory getCommandFactory();
}
process() 메서드는 CommandFactory를 이용해서 Command객체를 생성하고 있는데, getCommandFactory()메서드를 이용해서 CommandFactory클래스의 인스턴스를 구하고 있다. 여기서 getCommandFactory() 메서드가 의존객체를 구할 때 사용되는 룩업 메서드이다.
스프링에서 룩업 메서드에 대한 인젝션을 수행하려면 설정 파일에서 <lookup-method> 태그를 사용하면된다.
<bean ...>
<lookup-method name="getCommandFactory" bean="commandFactory" />
</bean>
<lookup-method> 태그의 name 속성은 룩업 메서드의 이름을 입력하고 bean속성은 룩업 메서드가 리턴할 빈 객체의 식별값을 입력한다. 예를 들어, 위 코드는 룩업 메서드로 getCommandFactory() 메서드를 지정하였고, getCommandFactory() 메서드가 commandFactory빈을 리턴하도록 설정하였다. 따라서 Processor.process() 메서드는 commandFactory빈을 사용하게 된다.
스프링은 상속을 이용해서 룩업 메서드를 구현(오버라이딩)하기 때문에, 룩업 메서드는 다음과 같은 규칙을 지켜야 한다.
- 접근 수식어가 public이나 protected 여야 한다.
- 리턴타입이 void가 아니다.
- 인자를 갖지 않는다.
- 추상 메서드도 가능하다.
- final이 아니다.
출처 : SPRING 3.0 프로그래밍 (웹개발자를 위한) 최범균 저
'프로그래밍 > Spring' 카테고리의 다른 글
@Autowired 어노테이션 (0) | 2018.12.18 |
---|---|
@Required 어노테이션 (0) | 2018.12.18 |
Bean 범위(scope) (0) | 2018.12.18 |
AOP(Aspect Oriented Programming)와 스프링(Spring) (0) | 2018.12.17 |
스프링(Spring) 프레임워크 & DI(Dependency Injection)패턴 (0) | 2018.12.17 |