스프링 프로젝트를 할때 xml 설정파일 둘다 등록해야한다.
* 디펜던시(Dependency)
- 외부 라이브러리 또는 모듈을 말한다. Build Tool(Maven 또는 Gradle)을 사용하여 프로잭트에 라이브러리를 추가하며, 라이브러리는 스프링 애플리케이션에서 사용될 수 있도록 클래스 경로(classpath)에 추가된다.
- 외부 라이브러리에 대한 종속성을 관리한다.
<!-- Maven dependency for Spring Framework -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.10.RELEASE</version>
</dependency>
dependencies {
implementation 'org.springframework:spring-context:5.3.10.RELEASE' // 사용하려는 Spring 버전에 맞게 버전을 지정합니다.
}
XML 설정 파일 작성
스프링 애플리케이션의 구성을 정의한다. 스프링 컨테이너에 대한 설정 및 빈정의를 포함한다.
1. 네임스페이스 선언
<?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">
* 네임스페이스: 구분이 가능하도록 정해놓은 범위나 영역으로 요소 간의 이름 충돌을 방지한다.
* XML 네임스페이스는 URI로 식별된다.
* xmlns(XML Namespace), xsi (XML Schema Instance)
* xmlns는 네임스페이스를 정의하여 xml데이터의 충돌을 방지하고, xsi는 xml 스키마와 관련된 정보를 정의하여 schemaLocation속성을 사용하여 스키마 위치를 지정하고 유효성을 검사를 수행한다.
* util 컬렉션의 구성, 상수 참조 등과 같은 유틸리티 구성을 처리한다.
* context: Spring 애플리케이션의 "플러밍(plumbing)" 부분을 담당
2. 빈 정의
빈(Bean)은 스프링 애플리케이션에서 관리하고자 하는 객체로 <bean> 태그를 사용한다.
각 빈의 클래스, 속성, 생성자 인자, 초기화 메서드, 종료 메서드 등을 정의한다.
<bean id="myBean" class="com.example.MyClass">
<!-- 빈의 속성 설정 -->
<property name="propertyName" value="propertyValue" />
</bean>
- id : 빈 이름(id) 설정, id를 통해 참조할 경우가 있을때 설정하고, getBean(), ref 속성으로 빈을 참조
- class : 빈 타입 설정
- scope : 빈의 scope 설정. singleton/prototype
- primary : true를 지정하여 같은 타입의 빈이 여러개 일때 우선적으로 사용할 빈 설정
- lazy-init : true를 지정하여 빈을 사용할 때 객체가 생성되도록 설정
- init-method : 빈 객체가 생성될때 호출할 메소드 설정
- destroy-method : 빈 객체가 소멸될때 호출할 메소드 설정
3. 애플리케이션 컨텍스트 설정
- XML 파일은 스프링 애플리케이션 컨텍스트를 생성하고 설정합니다. 컨텍스트를 생성하려면 <beans> 엘리먼트를 사용합니다.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 빈 정의 -->
<bean id="myBean" class="com.example.MyBean">
<!-- 빈의 속성 설정 -->
<property name="propertyName" value="propertyValue" />
</bean>
<bean id="userService" class="com.example.UserService">
<!-- 의존성 주입 -->
<property name="userRepository" ref="userRepository" />
<!-- 빈의 생명주기 관리 -->
<init-method="init" destroy-method="destroy" />
</bean>
<bean id="userRepository" class="com.example.UserRepository" />
<!-- 프로퍼티 설정 -->
<util:properties id="myProperties">
<prop key="database.url">jdbc:mysql://localhost/mydb</prop>
</util:properties>
<!-- AOP 설정 -->
<aop:config>
<aop:aspect ref="myAspect">
<aop:pointcut expression="execution(* com.example.*Service.*(..))" id="myPointcut" />
<aop:advisor advice-ref="myAdvice" pointcut-ref="myPointcut" />
</aop:aspect>
</aop:config>
</beans>
- 의존성 주입:
스프링에서는 의존성 주입(Dependency Injection)을 통해 빈 간의 관계를 설정합니다.
다른 빈을 주입하려면 <property> 또는 <constructor-arg> 엘리먼트를 사용합니다. - 빈의 생명주기 관리:
각 빈의 생명주기 관리를 위해 init-method 및 destroy-method 속성을 사용합니다.
이를 통해 빈의 초기화 및 소멸 메서드를 설정할 수 있습니다. - 프로퍼티 설정:
애플리케이션에서 사용하는 환경 변수, 데이터베이스 연결 정보, 서비스 URL 등과 같은 설정 값을 정의합니다. - AOP 설정:
스프링 AOP(Aspect-Oriented Programming) 설정을 포함하여 애스펙트와 어드바이스(Advice)를 정의합니다. - 애플리케이션 컨텍스트 설정:
XML 파일은 스프링 애플리케이션 컨텍스트를 생성하고 설정합니다.
컨텍스트를 생성하려면 <beans> 엘리먼트를 사용합니다.
4. 설정 파일 저장
작성한 XML 설정 파일을 애플리케이션 클래스와 같은 디렉토리에 저장하거나 클래스패스에 위치시켜야 합니다.
* XML 설정파일을 WEB-INF 디렉토리에 저장한다.
- 클래스로더(classloader)가 WEB-INF/classes 및 WEB-INF/lib디렉토리를 확인하여 클래스패스에 추가한다.
- WEB-INF 디렉토리는 일반적으로 웹 클라이언트(브라우저)가 접근 할 수 없다. 외부 사용자가 파일에 엑세스 할 수 없어 보안이 강화된다.
* 애플리케이션을 설정하는 순서
1. 애플리케이션 구동: 스프링컨테이너 생성x
2. Spring IoC 컨테이너 생성 및 xml 설정파일 로드:
- ClassPathXmlApplicationContext를 사용하여 XML 설정 파일(클래스패스에 위치)을 로드하여 컨테이너를 생성
- FileSystemXmlApplicationContext를 사용하여 파일 시스템 경로에서 XML설정 파일을 로드하여 컨테이너를 생성
3. 빈(Bean)등록:
- 설정파일에 정의된 빈들은 스프링 IoC 컨테이너에 등록되고,
- 클래스로더를 통해 빈의 클래스가 로드되어 메모리에 올리고,
- 빈의 초기화 메서드가 호출된다.
4. 애플리케이션 실행: 설정된 빈들을 통해 로직이 실행되고, 빈들은 필요한 의존성을 가지며 스프링 컨테이너에 의해 관리됨
5. 애플리케이션 종료: 빈 종료 메서드(destroy-method)가 호출된다.
- Spring IoC 컨테이너는 애플리케이션의 설정을 관리하고, 빈의 초기화, 런타임 시 필요한 빈의 제공 등의 역할을 한다.
XML 스키마
XML 설정파일을 작성 할때 XML스키마의 규칙을 참고하여 작성한다.
40.2.8 context 스키마
context 스키마는 ApplicationContext 설정과 관련된 부분을 다룬다.
빈 등록은 XML, 빈 설정은 자바 애너테이션으로 할 경우 사용
<property-placeholder/>
- 외부 프로퍼티 파일의 값을 spring 빈의 프로퍼티로 주입하는데 사용
- 주로 데이터베이스 연결 정보, 환경설정, 서비스의 엔트포인트 URL등을 설정할 때 사용
- root-context.xml 혹은 servlet-context.xml 파일안에 태그를 이용하여 로드
- 실제 값은 properties 혹은 yml 값은 외부 설정값을 관리하는 외부 속성 파일에서 가져옵니다.
- 프로퍼티명 = 값 형식으로 작성
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.사용자 이름=sa
jdbc.password=루트
1) PropertySourcesPlaceholderConfigurer 클래스를 빈으로 등록 ${프로퍼티명} 형식으로 사용
// 한개의 프로퍼티 지정
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations" value="classpath:com/something/jdbc.properties"/>
</bean>
// 다수의 속성 파일 위치 정의
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>프로퍼티 파일</beans:value>
<value>프로퍼티 파일</beans:value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
* ${property-name}대체할 값은 Ant, log4j 및 JSP EL 스타일을 따르는 형식의 자리 표시자로 지정됩니다.
2) <context:property-placeholder location="프로퍼티 파일"> 태그를 이용하여 로드
- Spring 2.5에 도입된 네임스페이스
- 외부 속성 파일에서 값을 읽어 올 수 없으면 Spring Environment속성과 일반 Java System속성을 확인한다.
// 한개의 속성 파일 위치 정의
<context:property-placeholder location="classpath:com/something/jdbc.properties"/>
// 다수의 속성 파일 위치 정의
<context:property-placeholder location="classpath:com/something/jdbc.properties,classpath:com/something/other.properties"/>
<spring-configured/>
- Spring Framework 내에서 AspectJ 컴파일 타임 위빙(Compile-Time Weaving)을 지원하는 방법 중 하나입니다. 이를 통해 @Configurable 어노테이션을 사용한 클래스를 자동으로 Spring IoC 컨테이너의 빈으로 등록하고, 자동적으로 의존성 주입을 처리할 수 있습니다.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- spring-configured 설정 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 다른 빈 정의 -->
</beans>
@Configurable
- 클래스를 spring bean으로 구성 가능하게 만든다.(XML 구성파일에 Bean을 정의하지 않는다)
- 주로 스프링 컨테이너 외부에서 생성된 객체에 spring의 의존성을 주입할 때 사용한다.
- 해당 클래스의 인스턴스를 Spring IoC 컨테이너가 관리하는 bean으로 만들 수 있다.
이를 통해 해당 클래스의 인스턴스를 new 연산자로 직접 생성하지 않고(Spring 관리 x), Spring이 관리하도록 할 수 있다.
출력
Dog's Name: Lucy
Dog's Age: 4
1. `@Configurable` 어노테이션을 사용하여 Bean을 정의(XML 구성 파일에 빈을 정의 하지 않음)
package com.example.animals;
import org.springframework.beans.factory.annotation.Configurable;
// bean정의의 이름을 명시적으로 지정하려면 @Configurable("Dog") 이렇게 사용한다.
@Configurable
public class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
// Getter 메서드
public String getName() {
return name;
}
public int getAge() {
return age;
}
// Setter 메서드
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
Java 코드에서 스프링 IoC컨테이너를 초기화하고, `@Configurable` 어노테이션이 적용된 클래스의 빈을 가져온다.
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.example.animals.Dog;
public class Main {
public static void main(String[] args) {
// XML 구성 파일을 사용하지 않음. @Configurable 어노테이션이 클래스를 빈으로 관리함.
// Spring IoC 컨테이너 초기화
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// Dog 빈을 가져옴
Dog dog = context.getBean(Dog.class);
// Dog 객체 사용
System.out.println("Dog's Name: " + dog.getName());
System.out.println("Dog's Age: " + dog.getAge());
}
}
스프링 빈을 정의하는 설정 클래스 AppConfig에서 속성 값을 가져온다. (@Configuration 어노테이션으로 표시)
package com.example.animals;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public Dog dog() {
return new Dog("Lucy", 4);
}
}
2. <bean> 요소로 빈을 정의 (XML 구성 파일에 빈을 정의)
<!-- XML 구성 파일 (spring-config.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">
<!-- Dog 빈의 정의 -->
<bean id="dog" class="com.example.animals.Dog">
<constructor-arg value="Buddy"/> <!-- 생성자 인자 설정 -->
<constructor-arg value="3"/>
</bean>
</beans>
Java 코드에서 스프링 IoC 컨테이너를 초기화하고 빈을 가져온다.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.example.animals.Dog;
public class Main {
public static void main(String[] args) {
// XML 구성 파일을 사용하여 Spring IoC 컨테이너를 초기화
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// "dog" 빈을 가져옴
Dog dog = context.getBean("dog", Dog.class);
// Dog 객체 사용
System.out.println("Dog's Name: " + dog.getName());
System.out.println("Dog's Age: " + dog.getAge());
}
}
3. `new`연산자로 직접 객체를 생성하는 코드
public class Main { //진입점
public static void main(String[] args) {
// 스프링 빈이 아닌 클래스 (스프링 컨테이너의 관리를 받지 않는 클래스)
Dog dog = new Dog("Lucy", 4); // 객체 생성 및 초기화
// 객체 생성 후 사용
System.out.println("Dog's Name: " + dog.getName());
System.out.println("Dog's Age: " + dog.getAge());
}
}
class Dog {
private String name; //멤버변수
private int age;
public Dog(String name, int age) { // 생성자
this.name = name; // 멤버변수 초기화(강한결합도)
this.age = age;
}
public String getName() { //객체의 속성을 반환
return name;
}
public int getAge() { //객체의 속성을 반환
return age;
}
}
- <bean> 방법에서는 XML 구성 파일을 사용하여 빈을 정의하고 설정하며, 빈의 이름과 속성을 명시적으로 지정해야한다.
- @Configurable 방법에서는 XML 구성 파일을 사용하지 않고 어노테이션을 클래스에 적용하여 클래스를 스프링 빈으로 관리합니다. 빈의 이름과 속성을 XML 파일에서 정의하지 않아도 된다.
@autowired
- Spring IoC 컨테이너에서 자동으로 의존성 주입을 수행하도록 한다.
- bean이 관리하는 클래스에 빈이 주입받을 클래스나 컴포넌트에 의존성을 자동으로 주입받는다.
- 느슨한 결합, 코드의 단순화
@autowired를 사용하 Spring IoC 컨테이너는 `Myclass`빈을 생성할때 `SomeBean`빈을 주입한다.
= SomeBean이 빈으로 정의 되어 있어야한다.
@Autowired
public MyClass(SomeBean someBean) {
this.someBean = someBean;
}
XML 구성 파일에 `SomeBean`을 빈으로 정의
<bean id="someBean" class="com.example.SomeBean">
<!-- 다른 프로퍼티 설정, 생성자 인자 설정 등 -->
</bean>
Java 설정 클래스의 @Bean 메서드를 사용하여 `SomeBean`을 빈으로 정의
<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="someBean" class="com.example.SomeBean" />
<bean id="myClass" class="com.example.MyClass">
<constructor-arg ref="someBean" />
</bean>
</beans>
- <annotation-config/>
- Spring 어노테이션( @Component, @Autowired, @Service, @Controller, @Repository )을 사용하여 정의한 빈을 활성화하는 데 사용
- <context:annotation-config> 또는 <context:component-scan>과 함께 사용
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 다른 빈 정의 -->
<context:annotation-config/>
</beans>
@autowired
- Spring IoC 컨테이너에서 자동으로 의존성 주입을 수행하도록 한다.
- bean이 관리하는 클래스에 빈이 주입받을 클래스나 컴포넌트에 의존성을 자동으로 주입받는다.
- 느슨한 결합, 코드의 단순화
@autowired를 사용하 Spring IoC 컨테이너는 `Myclass`빈을 생성할때 `SomeBean`빈을 주입한다.
= SomeBean이 빈으로 정의 되어 있어야한다.
@Autowired
public MyClass(SomeBean someBean) {
this.someBean = someBean;
}
XML 구성 파일에 `SomeBean`을 빈으로 정의
<bean id="someBean" class="com.example.SomeBean">
<!-- 다른 프로퍼티 설정, 생성자 인자 설정 등 -->
</bean>
Java 설정 클래스의 @Bean 메서드를 사용하여 `SomeBean`을 빈으로 정의
<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="someBean" class="com.example.SomeBean" />
<bean id="myClass" class="com.example.MyClass">
<constructor-arg ref="someBean" />
</bean>
</beans>
- <component-scan/>
- Spring 컴포넌트 스캔(Component Scan)을 활성화하며, 패키지를 스캔하여 어노테이션을 사용하여 정의한 빈을 자동으로 검색하고 등록한다.
- 주로 @Component, @Service, @Repository, @Controller와 같은 어노테이션을 사용한 클래스를 찾아서 빈으로 등록
- 어노테이션을 사용하여 빈을 정의하고 스프링 컨테이너에 등록할 수 있으며, XML에서 빈을 일일히 정의하는 번거로움을 줄일 수 있다.
- 빈 후처리기들을 자동으로 활성화하여 명시적으로 설정하지 않아도 된다.
<!-- spring-config.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 컴포넌트 스캔을 활성화할 패키지 설정 -->
<context:component-scan base-package="com.example.beans" />
</beans>
1. <context:component-scan> 사용 코드
- @Component 어노테이션을 사용하여 빈을 자동으로 스캔 및 등록
<!-- spring-config.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
// 패키지를 등록하여 해당 패키지를 스캔하여 bean을 자동으로 등록
<context:component-scan base-package="com.example.beans" />
</beans>
// MyBean.java
package com.example.beans;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private String name;
private int age;
public MyBean() {
this.name = "Lucy";
this.age = 4;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
// Main.java
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.example.beans.MyBean;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
MyBean myBean = context.getBean(MyBean.class);
System.out.println("MyBean's Name: " + myBean.getName());
System.out.println("MyBean's Age: " + myBean.getAge());
}
}
2. <context:component-scan>를 사용하지 않고 XML로 빈을 정의한 코드
- XML에 해당 클래스를 빈을 명시적으로 정의
<!-- spring-config.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">
// myBean 클래스를 bean으로 직접 등록
<bean id="myBean" class="com.example.beans.MyBean" />
</beans>
// MyBean.java
package com.example.beans;
public class MyBean {
private String name;
private int age;
public MyBean() {
this.name = "Lucy";
this.age = 4;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
// Main.java
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.example.beans.MyBean;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
MyBean myBean = context.getBean("myBean", MyBean.class);
System.out.println("MyBean's Name: " + myBean.getName());
System.out.println("MyBean's Age: " + myBean.getAge());
}
}
출처:
ChatGPT by OpenAI
https://docs.spring.io/spring-framework/reference/core/appendix/xsd-schemas.html
https://docs.spring.io/spring-framework/reference/core/appendix/xml-custom.html#xsd-custom-schema
https://www.tcpschool.com/xml/xml_basic_namespace
https://m.blog.naver.com/hj_kim97/222654116467