클래스 생성
관례적으로 패키지명은 groupId + artifactId으로 만듭니다
지난시간에 프로젝트를 생성했을때 입력했던 groupId인 com.spring과 artifactId인 basic을 합쳐
com.spring.basic이라는 패키지에 HelloSpring이라는 클래스파일을 생성해봅니다.
package com.spring.basic;
import org.springframework.context.support.GenericXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
System.out.println("안녕 스프링~!~!");
}
}
컴파일과 빌드가 잘 되는지 체크해보기 위한 코드를 작성해보고 실행합니다.
동일한 패키지에 SpringTest클래스파일을 하나 더 생성해줍니다.
만들어진 SpringTest클래스에 메인메서드없이 hello()라는 메서드하나를 생성하고 메서드를 호출했을때 문자열을 출력하도록 하는 코드를 메서드 내부에 작성해 보겠습니다
package com.spring.basic;
public class SpringTest {
public void hello() {
System.out.println("스프링 객체 주입 테스트~ : 안녕안녕~");
}
}
우리가 HelloSpring클래스에서 "스프링 객체 주입 테스트~ : 안녕안녕~"라고 출력하고싶다면 어떻게 하면 될까요
기본적인 자바문법으로는 해당 문자열을 출력시켜주는 메서드 hello()가 선언되어 있는 SpringTest클래스의 객체를 생성해야합니다.
hello()메서드를 호출해야 해당 문자가 출력이 될것이며 hello()메서드는 SprintTest클래스에 선언되어 있기 때문에 SpringtTest클래스의 객체를 생성해야만 합니다.
그럼 문자열 출력 코드를 주석처리 해 준 후 다음과같이 코드를 작성해보도록 합니다
package com.spring.basic;
import org.springframework.context.support.GenericXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
//System.out.println("안녕 스프링~!~!");
SpringTest st = new SpringTest();
st.hello();
}
}
HelloSprint클래스에 위와같이 코드를 하고 실행한다면
SprintTest클래스에 선언된 hello()메서드가 호출되며 메서드에 선언된 문자열 출력이 실행어 콘솔창에
"스프링 객체 주입 테스트~ : 안녕안녕~"이라는 문자열이 출력됩니다.
이게 바로 기존에 알고있던 객체를 통한 활용 입니다.
객체를 생성하고 해당 객체의 클래스에 선언된 멤버나 메서드를 참조해서 작업을하는 기존방식의 자바코딩방법
, 객체를 사용하는 방법이죠.
이것이 스프링에서는 어떻게 바뀌고 어떤방식을 통해 사용 되는지 코드를통해 구현해보도록 하겠습니다.
스프링 방식의 객체생성 방법
스프링에서의 객체생성방법은 필요할때마다 객체를 생성하는것이 아니라 미리 만들어놓고 필요할때 빼서씁니다
미리 집사(Container)한테 말해놓습니다 설정파일(xml)을 통해서.
자바에서는 일반적으로 특정 클래스의 필드나 메서드 같은 기능과 정보들이 필요할때 new() 연산자를 통해 객체를 만들어 사용했습니다.
하지만 스프링에서는 조금 다른방식으로 객체를 생성하여, 클래스간 클래스끼리 의존관계에 있을때 즉, 어떠한 클래스의 객체가 필요할때 객체를 주입시켜 줍니다.
스프링은 기본적으로 ApplicationContext 이라는 컨테이너기능을 해주는 클래스가 있으며, xml에서 Bean등록을 하게되면 이같은 컨테이너에 객체가 미리 등록이 됩니다.
그리고 우리는 필요할때 어노테이션 선언 하나만으로 해당 컨테이너로부터 객체를 주입받는데 이를 의존객체 주입이라고합니다.
스프링 방식의 Low한 코드로는 GenericXmlApplcationContext클래스를 사용하여 컨테이너로 부터 객체를 불러와 주입시켜줄 수 있습니다.
먼저 설정파일을 만들어보겠습니다.
설정파일은 src/main/resources에 저장하고 관리합니다.
해당 폴더에 test-config.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
만들어진 test-config.xml파일에 이렇게 코드를 작성해줍니다.
먼저 해당 코드를 아주 간단히 가볍게 해석해보겠습니다.
xmlns : xml의 네임스페이스, 태그를 식별하기위한 이름입니다.
- 스프링프레임워크가 제공하는 beans라는 설정에 등록되있는, 이 문서에 등록되있는 설정을 이용하겠다
- beans에 태그들을 이용하겠다 beans안에는 bean태그가 존재한다 그것을 사용하기위해서 네임스페이스 - 를 이용한다 라는 뜻입니다
xmlns:xsi : xml정보가 가리키는 주소, 정보가 들어있는 주소, 상대주소.
xsi:schemaLocation: 두개의 값이 공백으로 구분됩니다. 첫번째는 사용할 네임스페이스, 두번째는 참조할 네임스페이스 위치.
사용할 네임스페이스와 위치를 다시한번 공백을통해 정해준다 라는 의미로 보면 되겠습니다.
설정파일에 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="test" class="com.spring.basic.SpringTest" />
</beans>
<bean id="test" class="com.spring.basic.SpringTest"/>이 형태는 JSP에서 유즈빈 액션태그의 느낌과 흡사합니다.
class에 선언한 해당 패키지 경로에 있는 클래스파일 (com.spring.basic.SpringTest) 을 객체화 한 후 bean id에 test 라고 객체명 역할을 할수 있도록 지정해줬습니다.
이것은 SpringTest.java의 객체, 메인에서 쓰고있는 SpringTest 클래스의 객체를 미리 등록해놓고 항상 준비해놔라 라는 의미 입니다.
조금 더 쉽고 재밌게 이야기로 풀어보자면 집사(Container)에게 "야 내가 'SpringTest.java'가 계속 필요할거같거든? 원할때마다 가져와야해? 이름은 'test'야 내가 Test 갖고오라고 하면 갖고와야해"라고 말하고 있는것입니다.
이렇게 코드등록을 해놓은 후 저장하고 HelloSprint클래스파일로 돌아갑니다.
main메서드에 선언된 모든 코드 내용을 지우고 아래와같이 코드해줍니다
package com.spring.basic;
import org.springframework.context.support.GenericXmlApplicationContext;
public class HelloSpring {
public static void main(String[] args) {
GenericXmlApplicationContext ct =
new GenericXmlApplicationContext("classpath:test-config.xml");
SpringTest st =
ct.getBean("test",SpringTest.class);
st.hello();
ct.close();
}
}
test-config.xml에 설정을 담아놓는 접시가 필요합니다 그래서 우리는 설정파일을 읽어오는객체를생성하는데
이것의 이름은 GenericXmlApplicationContext 입니다
new() 연산자로 GenericXmlApplicationContext 객체를 생성해주고 생성자 매개값으로 읽어들일 xml 설정파일을 적으면되는데, 설정한 파일은 resources폴더이 있고, 폴더에 바로 접근할 때 자동으로 매핑되는 키워드는 classpath입니다. 이 키워드를 통해 resources폴더에 접근하게 됩니다.
classpath:test-config.xml 이라고 문자열로 생성자 인자값으로 넣어주면 src/main/resources/test-config.xml파일을 로드 합니다.
설정을 접시에 담아놓고 객체를 생성할때 SpringTest의 객체를 생성합니다.
이전까지는 new()연산자로 객체를 생성하였지만 ct.getBean()이라는 메서드를 호출하여 매개값에 설정한 이름 : "test", 해당 클래스파일형태 SprintTest.class를 각각 넣어준 후 SpringTest의 reperence변수 st에 저장합니다.
getBean()메서드로 집사(container)야 콩(객체)하나만 가져와봐. 필요하신 객체이름이뭔가요? 설정한 id인 "test"(객체이름), SpringTest.class형태로 가져오너라 라고 쉽고 재밌게 이야기로 표현할 수 있습니다
이것을 보면 test-config.xml에 선언한
<bean id="test" class="com.spring.basic.SpringTest" />
해당 코드에서 bean id가 객체명이되고 class에 입력한 클래스경로가 객체명의 클래스가 됩니다.
이것을 자바코드로 구현하면
SprintTest test = new SprintTest()
이렇게 객체를 생성하는것으로 정리할 수 있습니다.
스프링은 두가지 타입의 컨테이너를 제공합니다.
좀더 자세히 말하면
BeanFactory를 구현한 클래스로 컨테이너에 접근할 수 있고
ApplicationContext까지 구현한 클래스로 컨테이너에 접근할 수 있습니다.
보통 BeanFactory계열의 인터페이스만 구현한 클래스로는 컨테이너에 접근하진 않습니다.
스프링이 제공하는 다양한 기능(트랜잭션 처리, 자바코드 기반 스프링 설정, 어노테이션 등)을 사용하지 못하고 객체를 생성하고 DI처리밖에 하지 못합니다.
따라서 ApplicationContext 인터페이스를 구현한 클래스로 스프링 컨테이너에 접근하는데 색이 칠해진 5가지 클래스를 사용합니다.
GenericXmlApplicationContext |
XML파일을 설정정보로 사용해 스프링 컨테이너를 구현하는 클래스, 독립형 어플리케이션을 개발할 때 사용. |
다시 정리해보겠습니다.
Spring에서 객체를 xml파일에 등록하게되면 이것에 Container에 등록되게됩니다
SpringTest클래스에서 GenericXmlApplicationContext로 설정파일을 로드. 즉, 읽어들여서 설정파일에 등록된
객체를 읽습니다.
SpringTest클래스에서 메인메서드를 실행하면 xml설정파일로 미리 Container에 등록된 SpringTest객체를 Container로부터 꺼내와서 getBean()메서드로 객체화시킨 후 HelloSpring에 주입하게 되는것입니다.
야이~ 이게 더어려운데? 더복잡한데? 직접 객체를 생성하는것보다 편한게 하나도없는데? 아... 더복잡하다... 라고 생각할수 있지만 스프링의 기능이 이게 다가 아닙니다 여기서 부터 출발해서 이걸 다시 줄여 나아갑니다
우리가 의존성주입을 확인하려면 바로 여기 오늘 한 코드에서부터 출발해야합니다.
지금 코드는 길고 이게 지금은 편하든 불편하든 스프링의 방식은 미리 등록해놓고 끄집어내오는것입니다.
객체를 직접 생성않고 미리 등록 해놓습니다.
나중에는 이런짓 하지도않습니다.
변수선언해놓고 자동으로 끄집어 내옵니다
지금 한코드가 끄집어 내 오는것을 명시적으로 코드한것입니다
'SpringFramework' 카테고리의 다른 글
Spring Legacy Mybatis Execute Query 콘솔출력 (0) | 2024.02.18 |
---|---|
[Swagger3] spring doc 2.1.0 설정 및 Map<String,Object> 스키마 (0) | 2023.07.27 |
SpringData에서 제공하는 Pageable에 대한 잘못된 블로그 포스팅 (1) | 2023.02.20 |
SLF4J Logback 설정 및 전역 컨트롤러 선언 (0) | 2022.11.20 |
미완성 [ property / 커맨드객체 / ${EL} / #{ } ] 문법별 set/get 메서드명 필드명 참조 기준 확인] (0) | 2020.09.04 |