주의사항 : SNAPSHOT 버전은 Spring Boot Team이 현재 개발하는 버전으로서 새로운것을 배울때 사용은 부적합.
// AppGamingBasicJava.java
package com.wjdtn747.springframework;
import com.wjdtn747.springframework.game.GameRunner;
import com.wjdtn747.springframework.game.MarioGame;
public class AppGamingBasicJava {
public static void main(String[] args) {
var marioGame = new MarioGame();
var gameRunner = new GameRunner(marioGame);
gameRunner.run();
}
}
// GameRunner.java
package com.wjdtn747.springframework.game;
public class GameRunner {
MarioGame game;
public GameRunner(MarioGame game){
this.game = game;
}
public void run(){
System.out.printf("Running game:%s",game);
game.up();
game.down();
game.left();
game.right();
}
}
// MarioGame.java
package com.wjdtn747.springframework.game;
public class MarioGame {
public void up(){
System.out.println("jump");
}
public void down(){
System.out.println("go into a hole");
}
public void left(){
System.out.println("go back");
}
public void right(){c
System.out.println("go forward");
}
}
각 MarioGame , GameRunner , AppGaingBasicJava class간에는 강한 결합으로 연결되어있음!
// GamingConsole.java
package com.wjdtn747.springframework.game;
public interface GamingConsole {
public void up();
public void down();
public void left();
public void right();
}
// AppGamingBasicJava.java
package com.wjdtn747.springframework;
import com.wjdtn747.springframework.game.GameRunner;
import com.wjdtn747.springframework.game.MarioGame;
import com.wjdtn747.springframework.game.SuperContraGame;
public class AppGamingBasicJava {
public static void main(String[] args) {
var marioGame = new MarioGame();
var scg = new SuperContraGame();
var gameRunner1 = new GameRunner(scg);
var gameRunner2 = new GameRunner(marioGame);
gameRunner1.run();
gameRunner2.run();
}
}
// GameRunner.java
package com.wjdtn747.springframework.game;
public class GameRunner {
GamingConsole game;
public GameRunner(GamingConsole game){
this.game = game;
}
public void run(){
System.out.printf("Running game:%s",game);
game.up();
game.down();
game.left();
game.right();
}
}
// MarioGame.java
package com.wjdtn747.springframework.game;
public class MarioGame implements GamingConsole {
public void up(){
System.out.println("jump");
}
public void down(){
System.out.println("go into a hole");
}
public void left(){
System.out.println("go back");
}
public void right(){
System.out.println("go forward");
}
}
// SuperContraGame.java
package com.wjdtn747.springframework.game;
public class SuperContraGame implements GamingConsole {
public void up(){
System.out.println("jump");
}
public void down(){
System.out.println("sit down");
}
public void left(){
System.out.println("go back");
}
public void right(){
System.out.println("shoooooot");
}
}

강한결합(Tight Coupling) : 예를 들어, AppGamingBasicJava class의 GameRunner() 생성자에는 매개변수로 MarioGame 객체만 들어갈 수 있고, 다른 객체의 경우 생성자에 활용되지 못함을 의미.
ex) 차량의 경우 엔진은 다른 엔진으로 함부로 교체를 못한다.
약한결합(Loose Coupling) : 예를 들어 생성자의 매개변수가 Interface인 경우 그 Interface를 상속하는 class 객체가 다 들어갈 수 있는것을 말함.
ex) 차량의 경우 타이어는 기본 규격만 같으면 교체가 가능하다.
사전지식 :
public class AppGamingBasicJava { public static void main(String[] args) { var gm = new MarioGame(); // 1: 객체생성 var gameRunner1 = new GameRunner(gm); // 2: 객체생성 + Dependencies(의존성)을 Wiring(종속) // ex ) gm 은 GameRunner의 Dependency임. gameRunner1.run(); } }
IoC Container 종류
- Bean Factory :
。기본적인 형식의 Spring Container.
。현재는 사용하지 않는다.- Application Context :
。Enterprise 기능이 존재하는 발전된 Spring Container
관련 기능 및 Annotation :
- AnnotationConfigApplicationContext():
。@Component로 선언된 class 또는 class 내 method가 @Bean으로 선언한 class로 부터 객체정보를 가져와서 Spring Context를 생성.
。Spring Container를 생성하고 인자로 전달된 class를 기반으로 Spring Bean들을 등록.- @Configuration :
。외부 라이브러리 혹은 내장 클래스를 Bean으로 등록 시 사용 ( 개발자가 직접 제어가 불가능 )
。1개 이상의 @Bean을 제공하는 class는 반드시 @Configuration를 선언.
자바 객체
- POJO( Plain Old Java Object ) :
。특정 기술(ex . Framework)에 종속되어있지 않은 상태로 개발하는 개념을 위해 등장한 언어.
。필드와 Getter ,Setter와 같은 기본 기능을 가지는 객체.- Java Bean :
。반복작업을 효율적으로 수행하기위한 Java의 재사용가능한 Class.
。POJO에 비해 더 많은 제약사항 존재.
。EJB(Enterprise Java Bean)에 의해 영향을 받는다.
。모든 field는 private로 구성되어있으며 getter & setter 로만 접근.
。전달 인자가 없는 기본생성자(no-arg)만을 가지는 형태의 class.
。Serialzable 이라는 interface 상속.// Java Bean 예시. class JavaBean implements Serializable { private int age; public JavaBean(){} public int getAge(){ return this.age; } public void setAge(int a){ this.age = a; } }- **Spring Bean** : 。Spring IoC Container가 관리하는 Java 객체. =Spring FrameWork에서 관리되는 모든것들은 전부 Spring Bean 。Spring에 의해 생성된 후 **Life Cycle(수명주기)**, **Dependencies(의존성)**이 관리되어짐. 。@Configuration으로 선언된 class 내부에 메소드를 @Bean으로 선언하여 Bean 생성. 。Spring Container인 Bean Factory 또는 Application Context에 의해 관리.
JVM(Java Virtual Machine)
- Java bytecode를 실행하기위한 가상프로세서
- 어느 플랫폼( CPU or OS ) 에서든 bytecode가 호환되게한다.
bytecode는 JVM이 존재하는 플랫폼이면 전부 실행이 가능하다.
ex ) java byte code(= compiled code) -> JVM -> Platfrom
이전까지는 JVM을 이용하여 객체를 생성하게 될 경우 사용자가 객체를 생성하고 결합 및 관리하는 코드를 직접 작성.
-> 수동으로 코딩하여 객체를 생성, 관리, 실행하는 대신 Spring FrameWork를 활용하여 자동으로 모두 관리하는 상태를 구축하고자함.
Java가 아닌 Spring 사용 시 이점
- 여러개의 Bean을 정의 가능.
- Spring에서 관리하는 객체를 검색할 수 있는 다양한 접근 방식을 제공.
- Spring framework에서 관리하는 기존 Bean을 재활용 할 수 있음.
- Bean에는 사용자가 지정한 이름을 설정 할 수 있다.
- Bean을 class 이름의 type으로 호출하거나 , Bean의 이름으로 호출할 수 있다.
- 기존 Bean을 활용해서 새로운 Bean을 구축할 수 있다.
- Spring context를 생성.
AnnotationConfigApplicationContext() 활용.- Spring Framework에 의해 관리할 수 있도록함
- @Configuration으로 생성한 Class를 정의하여 활용하고 @Bean으로 Spring Bean을 생성.
- JVM 내에서 Spring이 특정객체 name , age , person , person2 , address 를 bean으로 관리!
// App02HelloWorldSpring.java
package com.wjdtn747.springframework;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App02HelloWorldSpring {
public static void main(String[] args) {
// 1. Spring context를 생성. -> AnnotationConfigApplicationContext 활용
// 2. Spring Framework가 관리할 수 있게끔 설정하기.
// JVM내에 Spring Context 생성하기 위해 @configuration으로 미리 정의한 HelloWorldConfiguration class를 전달하여 새 instance를 생성.
// 이때 , 해당 class 내에는 data가 @Bean으로 정의되어있음.
var context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
// Spring Context 생성됨!
// 3. Spring Framework를 이용하여 Bean들을 참조하기.
System.out.println(context.getBean("name")); // context.getBean("변수명") : Bean 을 호출.
System.out.println(context.getBean("age"));
System.out.println(context.getBean(Person.class)); // 문자열로 변수명을 쓰는거 말고도 class 로 호출이 가능.
System.out.println(context.getBean("address2"));
}
}
// HelloWorldConfiguration.java
package com.wjdtn747.springframework;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// record 생성
record Person (String name , int age){};
record Address (String firstLine,String city){};
@Configuration
public class HelloWorldConfiguration {
@Bean
public Person person(){
return new Person("김정수", 18);
}
@Bean
public String name(){
return "이정수";
}
@Bean
public int age(){
return 27;
}
@Bean(name = "address2")
public Address address(){
return new Address("봉산동","원주");
}
}
@Configuration으로 미리 정의한 class
=> AnnotationConfigApplicationContext()에 전달하여 Spring Context 제작.
Record :
- JDK 16에서 추가된 새로운 기능.
- Java Bean을 제작 시 Getter , Setter , 생성자를 따로 정의하는 번거로움을 줄이기 위해서 제작!
=> 이들 메소드가 자동으로 생성됨.// record 생성 record Person (String name , int age){}; @Configuration public class HelloWorldConfiguration { @Bean public Person p(){ var p = new Person("김정수", 18); System.out.println(p.age()); // get method도 사용 가능! return p; // return 을 통해 record에서 생성자가 자동으로 생성되어서 받는다! }
@Bean이 정의된 Bean의 이름 수정하기
@Bean(name = "address2") public Address address(){ return new Address("봉산동","원주"); 기존 address 로 정의된 Bean의 이름이 address2로 변경됨.
기존 Spring Bean과 관계가 존재하는 새로운 Spring Bean 제작하는 방법
- #1. 메소드 호출을 통해서 새로운 spring bean 구축.
@Bean public Person person2MethodCall(){ return new Person(name(),age(),address()); } System.out.println(context.getBean("person2MethodCall"));이 경우 Bean으로 정의된 name 과 age와 address를 활용해서 method를 제작!
- #2. Parameter를 수정하여 spring Bean을 구축.
@Bean public Person person3Parameters(String name , int age , Address address2){ return new Person(name,age,address2); }person3Parameters 의 매개변수에 각 Bean들의 type과 명칭을 적고 이를 이용해 Person 객체를 제작 후 return.
@Component 와 @Configuration의 차이점?
- @Component :
。개발자가 직접 작성한 class를 Bean으로 등록할 때 사용
。@Controller , @Service , @Repository : @Component에서 구체화 된 형태.- @Configuration :
。외부 라이브러리 혹은 내장 클래스를 Bean으로 등록 시 사용 ( 개발자가 직접 제어가 불가능 )
。1개 이상의 @Bean을 제공하는 class는 반드시 @Configuration 사용.- 두 Annotation은 큰 차이가 없음.