전문가를 위한 스프링 5(Pro Spring 5) - Ch 2. 스프링 시작하기
2.1 스프링 프레임워크 가져오기
Maven, Gradle 같은 빌드 도구를 사용 || Github에서 Spring Library Checkout 후 사용
사용하려는 Spring에 적절한 JDK 사용하기
JVM(Java Virtual Machine) : 구현이 필요한 abstract machine, 자바 바이트 코드가 실행될 수 있는 실행 환경 제공하는 사양
JRE(Java Runtime Environment) : 실행 환경을 제공하는데 사용, JVM의 실제 구현체
JDK(Java Development Kit) : JRE, 메뉴얼 및 자바 도구들을 담고 있는 것
JDK12 이상, Spring 5.1.8 사용
2.2 스프링 모듈 이해하기
Spring 5.1.x.RELEASE는 21개의 모듈 제공
(aop, aspects, beans, beans-groovy, context, context-indexer, context-support, core, expression, instrument, jcl, jdbc, jms, messaging, orm, oxm, test, tx, web, webflux, web-mvc, websocket)
Maven
리소스 처리, 컴파일, 테스트, 패키징 등 application의 모든 빌드 라이프사이클 관리
Maven Pom.xml 예제
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.apress.prospring5.ch02</groupId>
<artifactId>hello-world</artifactId>
<packaging>jar</packaging>
<version>5.0-SNAPSHOT</version>
<name>hello-world</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>5.0.0.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
...
</plugin>
</plugins>
</build>
</project>
Gradle
Gradle build.gradle 예제
group 'com.apress.prospring5.ch02'
version '5.0-SNAPSHOT'
apply plugin: 'java'
repositories {
mavenCentral()
}
ext{
springVersion = '5.0.0.RELEASE'
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
dependencies {
compile group: 'log4j', name: 'log4j', version: '1.2.17'
... }
2.3 스프링 문서 사용하기
스프링의 모든 기능이 자바독으로 완전히 문서화될 뿐만 아니라 각 배포판에 포함된 레퍼런스 매뉴얼에도 모든 기능이 담겨져 있다.
2.4 스프링으로 Hello World 애플리케이션 만들기
1. 단순 hello world 출력
package com.apress.prospring5.ch2;
public class HelloWorld {
public static void main(String... args) {
System.out.println("Hello World!");
}
}
2. 명령줄 인자로 메시지 내용 전달
package com.apress.prospring5.ch2;
public class HelloWorldWithCommandLine {
public static void main(String... args) {
if (args.length > 0) {
System.out.println(args[0]);
} else {
System.out.println("Hello World!");
}
}
}
3-1. Message 출력 및 가져오는 로직 리팩토링 후 각각의 컴포넌트로 분리
package com.apress.prospring5.ch2.decoupled;
public interface MessageProvider {
String getMessage();
}
package com.apress.prospring5.ch2.decoupled;
public interface MessageRenderer {
void render();
void setMessageProvider(MessageProvider provider);
MessageProvider getMessageProvider();
}
3-2. 인터페이스 구현체
package com.apress.prospring5.ch2.decoupled;
public class HelloWorldMessageProvider implements MessageProvider {
@Override
public String getMessage() {
return "Hello World!";
}
}
package com.apress.prospring5.ch2.decoupled;
public class StandardOutMessageRenderer implements MessageRenderer {
private MessageProvider messageProvider;
@Override
public void render() {
if (messageProvider == null) {
throw new RuntimeException(
"You must set the property messageProvider of class:"
+ StandardOutMessageRenderer.class.getName());
}
System.out.println(messageProvider.getMessage());
}
@Override
public void setMessageProvider(MessageProvider provider) {
this.messageProvider = provider;
}
@Override
public MessageProvider getMessageProvider() {
return this.messageProvider;
}
}
3-3. 로직 분리한 메인 함수
package com.apress.prospring5.ch2.decoupled;
public class HelloWorldDecoupled {
public static void main(String... args) {
MessageRenderer mr = new StandardOutMessageRenderer();
MessageProvider mp = new HelloWorldMessageProvider();
mr.setMessageProvider(mp);
mr.render();
}
}
4-1. 속성파일에서 가져다 인스턴스로 만드는 팩터리 클래스 및 속성 파일(msf.properties)
package com.apress.prospring5.ch2.decoupled;
import java.util.Properties;
public class MessageSupportFactory {
private static MessageSupportFactory instance;
private Properties props;
private MessageRenderer renderer;
private MessageProvider provider;
private MessageSupportFactory() {
props = new Properties();
try {
props.load(this.getClass().getResourceAsStream("/msf.properties"));
String rendererClass = props.getProperty("renderer.class");
String providerClass = props.getProperty("provider.class");
renderer = (MessageRenderer) Class.forName(rendererClass).newInstance();
provider = (MessageProvider) Class.forName(providerClass).newInstance();
} catch (Exception ex) {
ex.printStackTrace();
}
}
static {
instance = new MessageSupportFactory();
}
public static MessageSupportFactory getInstance() {
return instance;
}
public MessageRenderer getMessageRenderer() {
return renderer;
}
public MessageProvider getMessageProvider() {
return provider;
}
}
renderer.class=com.apress.prospring5.ch2.decoupled.StandardOutMessageRenderer
provider.class=com.apress.prospring5.ch2.decoupled.HelloWorldMessageProvider
4-2. 변경에 따른 main 함수 변경
package com.apress.prospring5.ch2.decoupled;
public class HelloWorldDecoupledWithFactory {
public static void main(String... args) {
MessageRenderer mr =
MessageSupportFactory.getInstance().getMessageRenderer();
MessageProvider mp =
MessageSupportFactory.getInstance().getMessageProvider();
mr.setMessageProvider(mp);
mr.render();
}
}
5. 스프링으로 리팩토링 및 spring 구성 파일(app-context.xml)
package com.apress.prospring5.ch2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorldSpringDI {
public static void main(String args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/app-context.xml");
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="provider"
class="com.apress.prospring5.ch2.decoupled.HelloWorldMessageProvider"/>
<bean id="renderer"
class="com.apress.prospring5.ch2.decoupled.StandardOutMessageRenderer"
p:messageProvider-ref="provider"/>
</beans>
6. annotation을 사용한 구성
package com.apress.prospring5.ch2.annotated;
import com.apress.prospring5.ch2.decoupled.HelloWorldMessageProvider;
import com.apress.prospring5.ch2.decoupled.MessageProvider;
import com.apress.prospring5.ch2.decoupled.MessageRenderer;
import com.apress.prospring5.ch2.decoupled.StandardOutMessageRenderer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HelloWorldConfiguration {
// equivalent to <bean id="provider" class=".."/>
@Bean
public MessageProvider provider() {
return new HelloWorldMessageProvider();
}
// equivalent to <bean id="renderer" class=".."/>
@Bean
public MessageRenderer renderer(){
MessageRenderer renderer = new StandardOutMessageRenderer();
renderer.setMessageProvider(provider());
return renderer;
}
}
package com.apress.prospring5.ch2.annotated;
import com.apress.prospring5.ch2.decoupled.MessageRenderer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class HelloWorldSpringAnnotated {
public static void main(String... args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}
Github : https://github.com/Apress/pro-spring-5/tree/master/chapter02
2.5 정리
스프링 DI를 이용하여 전통적인 애플리케이션을 결합도를 낮추고, 확장 가능한 애플리케이션으로 변경
'IT > Spring' 카테고리의 다른 글
[Spring] 스프링 핵심 원리 - 기본편 (2) (0) | 2023.01.24 |
---|---|
[Spring] 스프링 핵심 원리 - 기본편 (1) (0) | 2023.01.09 |
[Spring][전문가를 위한 스프링 5] CH1. 스프링 소개 (0) | 2022.07.23 |
[Spring] Intellij에서 Spring + Maven 시작하기 (Mac) (0) | 2022.07.14 |
[Spring][Error] The dependencies of some of the beans in the application context form a cycle (0) | 2022.07.10 |
댓글