- 엔터프라이즈 급 어플리케이션을 구축할 수 있는 가벼운 솔루션이자 One-Stop-Shop
- 원하는 부분만 가져다 사용할 수 있도록 모듈화가 잘 되어 있다.
- IoC 컨테이너이다.
- 선언적으로 트랜잭션을 관리할 수 있다.
- 완전한 기능을 갖춘 MVC Framework를 제공한다.
- AOP 지원
- 스프링은 도메인 논리 코드와 쉽게 분리될 수 있는 구조를 가지고 있다.
*One-Stop-Shop : 모든 과정을 한꺼번에 해결하는 상점
- 컨테이너는 인스턴스의 생명주기를 관리한다.
- 생성된 인스턴스들에게 추가적인 기능을 제공한다.
- IoC란 Inversion Of Control의 약어이다. inversion은 도치, 역전이다. 보통 IoC를 제어의 역전이라고 번역한다.
- 개발자는 프로그램의 흐름을 제어하는 코드를 작성한다. 그런데, 이 흐름의 제어를 개발자가 하는 것이 아니라 다른 프로그램이 그 흐름을 제어하는 것을 IoC라고 말한다.
- DI는 Dependecny Injection의 약자로, 의존성 주입이라는 뜻이다.
- DI는 클래스 사이의 의존 관계를 빈(Bean)설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것을 말한다.
new -> maven -> quickstart
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
Bean의 조건
1. 기본 생성자를 가지고 있다
2. 필드는 private하게 선언한다.
3. getter, setter 메소드를 가진다. getName(), setName() 메소드를 name 프로퍼티(property)라고 한다. (용어 중요함)
(빈은 내가 생성하는 것이 아니기 때문에 규칙성을 가져야한다)
<spring.version> 4.3.14.RELEASE</spring.version>
properties란 상수처럼 사용할 수 있는 것들이다.
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
applicationContext.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="userBean" class="kr.or.connect.diexam01.UserBean"></bean>
</beans>
위 코드의 의미는 나중에 Spring이
kr.or.connect.diexam01.UserBean userBean = new kr.or.connect.diexam01.UserBean();
과 같은 의미다. 스프링 컨테이너는 이런 객체를 하나만 가지고 있다 (싱글톤 패턴)
package kr.or.connect.diexam01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextExam01 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
System.out.println("초기화 완료!");
UserBean userBean = (UserBean)ac.getBean("userBean");
userBean.setName("kang");
System.out.println(userBean.getName());
UserBean userBean2 = (UserBean)ac.getBean("userBean");
if (userBean == userBean2) {
System.out.println("같은 인스턴스입니다");
}
}
}
package kr.or.connect.diexam01;
public class Engine {
public Engine() {
System.out.println("Engine 생성자");
}
public void exec() {
System.out.println("엔진이 동작합니다");
}
}
package kr.or.connect.diexam01;
public class Car {
private Engine v8;
public Car() {
System.out.println("Car 생성자");
}
public void setEngine(Engine e) {
this.v8 = e;
}
public void run() {
System.out.println("엔진을 이용하여 달립니다");
v8.exec();
}
public static void main(String[] args) {
Engine e = new Engine();
Car c = new Car();
c.setEngine(e);
c.run();
}
}
main함수에서 Engine을 생성하고 setEngine을 호출하는 부분을 Spring이 대신 IoC를 통해 해줄 수 있다.
applicationContext.xml
<bean id = "e" class="kr.or.connect.diexam01.Engine"/>
<bean id = "c" class="kr.or.connect.diexam01.Car">
<property name = "engine" ref = "e"></property>
</bean>
property에 name은 setEngine에서 set다음 부분을 소문자로 바꾼 이름을 적어야한다. ref는 파라미터 값이다.
ApplicationContextExam02
package kr.or.connect.diexam01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextExam02 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) ac.getBean("c"); //Engine이 탑재된 Car 객체를 만들어서 반환한다.
car.run();
}
}
DI(의존성 주입)의 장점? Engine은 등장하지 않으므로 사용자는 사용할 Car 객체만 알면된다.
Java Config를 이용한 방법
ApplicationConfig
package kr.or.connect.diexam01;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ApplicationConfig {
@Bean
public Car car(Engine e) {
Car c = new Car();
c.setEngine(e);
return c;
}
@Bean
public Engine engine() {
return new Engine();
}
}
ApplicationContextExam03
package kr.or.connect.diexam01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ApplicationContextExam03 {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
Car car = (Car)ac.getBean(Car.class);
car.run();
}
}
Car.java
package kr.or.connect.diexam01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Car {
@Autowired
private Engine v8;
public Car() {
System.out.println("Car 생성자");
}
public void setEngine(Engine e) {
this.v8 = e;
}
public void run() {
System.out.println("엔진을 이용하여 달립니다");
v8.exec();
}
//
// public static void main(String[] args) {
// Engine e = new Engine();
// Car c = new Car();
// c.setEngine(e);
// c.run();
// }
}
Engine.java
package kr.or.connect.diexam01;
import org.springframework.stereotype.Component;
@Component
public class Engine {
public Engine() {
System.out.println("Engine 생성자");
}
public void exec() {
System.out.println("엔진이 동작합니다");
}
}
ApplicationConfig2.java
package kr.or.connect.diexam01;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("kr.or.connect.diexam01")
public class ApplicationConfig2 {
}
ApplicationContextExam04.java
package kr.or.connect.diexam01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ApplicationContextExam4 {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig2.class);
Car car = (Car)ac.getBean(Car.class);
car.run();
}
}