Spring MVC, Sptring boot

[Team Study] [Singleton2 - Java ver] Spring MVC 에서 Singleton에 대한 고찰

고인돌개발자 2021. 5. 3. 22:49

학습목표 :
   - Spring Framework 에서 싱글톤의 개념을 이해한다.
   - 싱글톤의 개념을 통해 IoC & DI 까지 살펴본다.
   - Java Singleton 과 다른 점을 살펴본다.

 

1. 준비하기 
    - 이클립스, 메이븐 설치등.. ( 참고 - old-developer.tistory.com/63 )

 

2. 클래스 개념도 및 스프링 컨테이너 보기 

<클래스 - 새가 날아간다, IoC 컨테이너, Di>

 

3. 설명 
   - Class  새(Bird)가 있다.
   - 참새(Sparrow) 와 독수리(Eagle)은 새를 상속받는다.

   - 참새와 독수리는 날수 있다. 날아가는 것을 인터페이스로 표현한다.

   - 참새와 독수리를 IoC 컨테이너에 넣어서 사용한다.

   - 인젝션을 설명하기 위해 억지스러운 class Who 를 만든다.

   - 위 내용이 이해가 안가면, 아래 소스를 직접 구현하면서 이해해 본다.

 

4. 코드 

  a) Bird.java

package com.spring.di.singleton.dijava;

public class Bird {

	String myName;
	
	public Bird() {
		System.out.println("Bird Constructor!!");
		this.myName = "Bird";
	}	
}

 

  b) IfFly.java

package com.spring.di.singleton.dijava;

public interface IfFly {
	
	String fly();
}

 

  c) Sparrow.java

package com.spring.di.singleton.dijava;

public class Sparrow extends Bird implements IfFly {
	
	private int sparrow_age=100;
	
	public Sparrow() {
		System.out.println("Sparrow Constructor!!");
		myName = "Sparrow";
	}

	@Override
	public String fly() {
		return myName +" can fly.";
	}

}

 

  d) Eagle.java

package com.spring.di.singleton.dijava;

import org.springframework.stereotype.Component;

public class Eagle extends Bird implements IfFly {
	
	private int eagle_age=100;
	
	public Eagle() {
		System.out.println("Eagle Constructor!!");
		myName = "Eagle";
	}

	@Override
	public String fly() {
		return myName +" can fly.";
	}

}

 

  e) ProgramSingleton.java (main())

 

package com.spring.di.singleton.dijava;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.spring.di.config.BeanConfig;


public class ProgramSingleton {

	public static void main(String[] args) {
		System.out.println("Di - java - ProgramSingleton Start!! \n");
		
		/* Ioc Container Call */	
		ApplicationContext context 
		= new AnnotationConfigApplicationContext(BeanConfig.class);
		
		System.out.println("------------------------!! \n");	
		
		// Eagle Instance
		//IfFly iffly = (IfFly) context.getBean("eagle");
		IfFly iffly = context.getBean(Eagle.class);
			System.out.println(iffly.fly());
		
		IfFly iffly2 = context.getBean(Eagle.class);
		IfFly iffly3 = context.getBean(Eagle.class);
		System.out.println("iffly "+iffly);
		System.out.println("iffly2 "+iffly2);
		System.out.println("iffly3 "+iffly3);
		
		// Sparrow Instance - Singleton
		System.out.println("------------------------!! \n");	
		IfFly iffly4 = context.getBean(Sparrow.class);
		IfFly iffly5 = context.getBean(Sparrow.class);
		System.out.println("iffly4 "+iffly4);
		System.out.println("iffly5 "+iffly5);
		
		// New Object - No Singleton
		IfFly iffly6 = new Sparrow(); 
		System.out.println("iffly6 "+iffly6);
		
		System.out.println("------------------------!! \n");	
		
		// Normal Injection 
		Who who = new Who();
		    who.setIffly(iffly4);
		    System.out.println("Normal Injection " + who);
		    who.doWho();
		    
		// DI injection 
		Who whodi = context.getBean(Who.class);
		System.out.println("\n DI Injection " + whodi);
		    whodi.doWho();
		
		//Who who = new Who();
		   
		
		System.out.println("------------------------!! \n");	
		
		System.out.println("ProgramSingleton End!!");		
	}
}

 f) BeanConfig.java

package com.spring.di.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.spring.di.entity.Exam;
import com.spring.di.entity.NewlecExam;
import com.spring.di.singleton.dijava.Eagle;
import com.spring.di.singleton.dijava.IfFly;
import com.spring.di.singleton.dijava.Sparrow;
import com.spring.di.ui.ExamConsole;
import com.spring.di.ui.InlineExamConsole;

@ComponentScan({"com.spring.di.ui","com.spring.di.entity","com.spring.di.singleton.dijava"})
@Configuration
public class BeanConfig {

	@Bean
	public Exam exam() {
		return new NewlecExam();
	}
	
	@Bean
	public ExamConsole console() {
		return new InlineExamConsole();
	}
	
	@Bean
	public IfFly sparrrow() {
		return new Sparrow();
	}
		
	@Bean
	public IfFly eagle() {
		return new Eagle();
	}
	
	
}

 

* 주의. 위 코드는 내 개인적인 프로젝트로 패키지 구조는 원하는 방식으로 변경해서 잘~ 사용해야 합니다.

  특히. 이클립스와 메이븐 설치 후 Spring web mvc 까지 잘 설치해야 구동이 가능합니다.

 

 

5. Java Singleton 과 다른 점은 ?

  - 자바의 싱글톤은 Static 메모리 영역에 해당 객체가 상주하고 있으며, 
    생성자가 Private 으로 구현되어, 어떤 형태로든 Singleton 의 모습을 유지한다.

 

  - 이에 반해 Spring frame work 의 Singleton 은 IoC 컨테이너에 있는 것을 사용할때만 
    Singleton이 되고, 해당 객체를 new 생성자로 생성할경우 IoC 싱글톤이 아닌 단일 인스턴스 객체로 사용이 가능해진다.

 

6. 마무리 
  - Spring Framework 의 Singleton 을 이해하기 위해서는 역시, JVM 의 메모리 구조를 알고 있어야 한다.
    나 또한 완전한 이해는 아니지만, IoC 컨테이너가 JVM 의 Static 메모리를 사용하는것은 확실하다.

  - 이 메모리 구조를 이해해야 IoC 와 DI 의 개념이 좀더 가까워진다.

 

* Singleton 공부는 결과적으로 메모리 구조에 대한 공부를 하게 했고, 

  이를 통해 Spring Frame Work 의 구조에도 한발 다가간 느낌을 갖게 된다.