파게로그
Spring Bean configuration 본문
Spring Bean configuration file 생성하기
docs.spring.io/spring-framework/docs/current/reference/html/core.html#xsd-schemas-beans
XML 파일을 생성해준다. 여기에서 Bean 객체를 생성한다.
<?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 definitions here -->
</beans>
XML에서 <bean>을 이용한 객체 생성
package admin.school;
import admin.school.entity.Exam;
import admin.school.entity.MidTermExam;
import admin.school.ui.ExamConsole;
import admin.school.ui.TableExamConsole;
public class Program {
public static void main(String[] args) {
/*
Exam exam = new MidTermExam(60, 70, 40, 80);
ExamConsole console = new TableExamConsole();
console.setExam(exam);
*/
console.print();
}
}
여기서 각주로 처리한 부분은 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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Exam exam = new MidTermExam(); -->
<bean id="exam" class="admin.school.entity.MidTermExam" />
<!-- ExamConsole tableExamConsole = new TableExamConsole(); -->
<bean id="tableExamConsole" class="admin.school.ui.TableExamConsole">
<!-- tableExamConsole.setExam(exam) -->
<property name="exam" ref="exam"></property>
</bean>
</beans>
<bean>
· id는 변수명이다.
· class는 반드시 패키지명까지 작성한다!
<property>
· 실제 속성(property)의 개념이 아니라, 단순히 메서드(setter)를 호출하는 것이다!
· ref 또는 value에 dependency의 이름(exam)을 넣는데, value형식이면 value에, ref타입이면 ref로 작성한다.
그렇다면 XML이라는 지시서를 통해 생성한 객체를 어떻게 Java 코드에서 이용할 수 있을까? 이는 곧 생성된 객체가 담겨 있는 Spring IoC Contatiner를 이용하는 것을 말한다. 그리고 이는 ApplicationContext라고 한다.
이 때 지시서의 위치를 지정하는 여러가지 방법을 위해 각각 함수가 준비되어 있다.
ClassPathXmlApplicationContext | application의 root로부터 경로 지정 |
FileSystemXmlApplicationContext | 일반 디렉터리를 통해 경로 지정 |
XmlWebApplicationContext | 웹 |
AnnotationConfigApplicationContext | 파일이 아니라 annotation |
package admin.school;
import admin.school.entity.Exam;
import admin.school.entity.MidTermExam;
import admin.school.ui.ExamConsole;
import admin.school.ui.TableExamConsole;
public class Program {
public static void main(String[] args) {
/*
XML 지시서로 넘어갈 부분
Exam exam = new MidTermExam(60, 70, 40, 80);
ExamConsole console = new TableExamConsole();
console.setExam(exam);
*/
ApplicationContext context = new ClassPathXmlApplicationContext("admin/school/setting.xml");
// ExamConsole console = ?
console.print();
}
}
현재 상태로는 Spring 라이브러리를 가져오지 않아서 에러가 발생한다. 프로젝트를 Maven Project로 변환해보자.
dependencies를 추가하면 되는데...
인덱스 다운로드가 비활성화되어 있다고 한다.
Rebuild Index를 누르면 아무 반응이 없어보이지만, Progress view를 통해서 아주 느리게 진행되는 것을 확인할 수 있다.
일단은 다음과 같이 해보자.
maven repository(Google) >
springframework >
spring context >
버전 선택 >
Maven 내용 복사 >
pom.xml의 <version> <build> 사이에 <dependencies>클립보드 내용</dependencies>
이제 IoC 컨테이너에, XML을 통해 지시한 객체들이 담겨있는 것이다. 이를 id를 통해 꺼내쓰거나 type을 통해서 꺼내 쓸 수 있는데, 이 컨테이너의 이름을 context라고 봐도 무방하다.
package admin.school;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import admin.school.entity.Exam;
import admin.school.entity.MidTermExam;
import admin.school.ui.ExamConsole;
import admin.school.ui.TableExamConsole;
public class Program {
public static void main(String[] args) {
/*
XML 지시서로 넘어갈 부분
Exam exam = new MidTermExam(60, 70, 40, 80);
ExamConsole console = new TableExamConsole();
console.setExam(exam);
*/
ApplicationContext context = new ClassPathXmlApplicationContext("admin/school/setting.xml");
ExamConsole console = (ExamConsole)context.getBean("console");
console.print();
}
}
위와 같이 id를 통해서 객체를 가져올 수 있다.
package admin.school;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import admin.school.entity.Exam;
import admin.school.entity.MidTermExam;
import admin.school.ui.ExamConsole;
import admin.school.ui.TableExamConsole;
public class Program {
public static void main(String[] args) {
/*
XML 지시서로 넘어갈 부분
Exam exam = new MidTermExam(60, 70, 40, 80);
ExamConsole console = new TableExamConsole();
console.setExam(exam);
*/
ApplicationContext context = new ClassPathXmlApplicationContext("admin/school/setting.xml");
ExamConsole console = (ExamConsole)context.getBean(ExamConsole.class);
console.print();
}
}
위와 같이 클래스 타입을 통해서 객체를 가져올 수도 있다. 이는 보다 선호되는 방법이지만, 같은 타입의 객체가 두 개 이상이라면 다른 구분 수단이 필요할 것이다.
constructor를 이용한 속성 값 설정
<?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">
<!-- Exam exam = new DdoongiExam(); -->
<bean id="exam" class="examadmin.di.entity.DdoongiExam">
<constructor-arg value="30" />
<constructor-arg value="50" />
<constructor-arg value="10" />
<constructor-arg value="40" />
</bean>
<!-- ExamConsole console = new GridExamConsole(); -->
<bean id="console" class="examadmin.di.ui.GridExamConsole">
<!-- console.setExam(exam); -->
<!-- <property name="setExam → set 생략하고 대문자는 소문자로 변경"></property> -->
<property name="exam" ref="exam"></property>
</bean>
</beans>
<constructor-arg>를 통해서 생성자를 통해 필드 값을 설정할 수 있다. 즉 MidTermExam의 public DdoongiExam(int kor, int eng, int math, int com) 생성자를 사용한 것이다.
<constructor-arg index="0" value="30" />
<constructor-arg index="1" value="50" />
<constructor-arg index="2" value="10" />
<constructor-arg index="3" value="40" />
위와 같이 인덱스를 설정함으로써, 생성자에 들어갈 파라미터를 헷갈리지 않게 할 수 있다. 이 때에는 인덱스를 명시했기에 순서가 변경되어도 무방하다.
<constructor-arg name="kor" value="30" />
<constructor-arg name="eng" value="50" />
<constructor-arg name="math" value="10" />
<constructor-arg name="com" value="40" />
또는 name을 통해서도 필드 값을 설정할 수 있다. 당연히 이 방법이 제일 편하다.
public DdoongiExam(int kor, int eng, int math) { }
public DdoongiExam(double kor, double eng, double math) { }
위와 같이 오버라이딩 된 생성자가 2개라면 어떻게 적절한 생성자를 선택할 수 있을까?
<constructor-arg name="kor" type="float" value="30" />
<constructor-arg name="eng" type="float" value="50" />
<constructor-arg name="math" type="float" value="10" />
<constructor-arg name="com" type="float" value="40" />
데이터 타입을 별도로 명시함으로써 적절한 생성자를 선택할 수 있다.
setter를 이용한 속성 값 설정
<bean id="exam" class="admin.school.entity.MidTermExam">
<property name="kor" value="30" />
<property name="eng" value="50" />
<property name="math" value="10" />
<property name="com" value="40" />
</bean>
<property>를 통해서 실제로 속성을 정의할 수 있는 것이 아니라, setter 메서드를 이용하는 것에 불과하다. 따라서 당연하게도 setter가 정의되어 있어야 한다.
한편 setter 이용 시 처리기를 추가할 수 있다. xmlns(XML Name Space)에 아래와 같이 추가해준다.
<beans xmlns= ...
xmlns:p="http://www.springframework.org/schema/p"
...>
이렇게 하면, <property> 대신 아래와 같이 간결한 작성이 가능하다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="exam" class="admin.school.entity.MidTermExam" p:kor="60" p:eng="70" p:math="40" p:com="80"/>
<bean id="tableExamConsole" class="admin.school.ui.TableExamConsole">
<property name="exam" ref="exam"></property>
</bean>
</beans>
Collection 생성과 목록 DI
List<Exam> exams = new ArrayList<>();
exams.add(new MidTermExam(70, 55, 80, 60));
Program.java에서의 위와 같은 코드의 결과를 XML에서 생성하고 초기화해보자.
ArrayList에 add하는 것은 setter와 무관하므로 <property>를 이용할 수 없다. ArrayList 초기화 시 생성자에 Collection을 전달할 수 있다는 것을 고려하면 된다.
<bean id="exams" class="java.util.ArrayList">
<constructor-arg> <!-- 설정하고자 하는 것이 Collection일 때에는 <list> 태그를 이용 -->
<list>
<!-- 생성자에 넘기는 방법 1 (새로운 객체를 생성) -->
<bean class="examadmin.di.ui" p:kor="20" p:eng="10" p:math="5" p:com="15" />
<!-- 생성자에 넘기는 방법 2 (이미 만들어둔 객체를 참조) -->
<ref bean="exam" />
</list>
</constructor-arg>
</bean>
여기서 <list>는 객체를 만드는 역할은 하지 못한다. 이렇게 하면 exam에는 두 개의 항목이 추가되어 있을 것이다.
List<Exam> exams = (List<Exam>)context.getBean("exams");
최종적으로는 위와 같이 사용할 수 있을 것이다.
util 이용
한편, 위 XML 코드에서 <list>는 목록을 세팅할 때 사용할 수 있으나, 객체를 만드는 역할은 하지 못한다. 이를 위해서는 util이 필요하다. xmlns와 xsi에 util 스키마를 사용할 수 있도록 설정하고, 이를 이용해 직접 ArrayList 객체를 생성할 수 있다. <util:list> 태그 내에서 다른 객체를 생성하는 것이 초기화 과정이다. <util:list>는 <list>와 처리기가 달라 실제로 객체를 만들 능력을 가지고 있다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<util:list id="exams" list-class="java.util.ArrayList">
<bean class="admin.school.entity.MidTermExam" p:kor="30" p:eng="50" p:math="10" p:com="40" />
<ref bean="exam" />
</util:list>
</beans>
'콤퓨타 왕기초 > Spring' 카테고리의 다른 글
annotation을 이용한 객체 생성 (0) | 2021.04.20 |
---|---|
Annotation을 이용할 때의 장점과 @Autowired 를 이용한 DI (0) | 2021.04.15 |
Spring 없이 직접 DI를 한다면? Spring의 역할 (0) | 2021.04.14 |
Dependency Injection, IoC Container (0) | 2021.04.12 |
Spring Framework (0) | 2021.04.12 |