Spring Core

์˜ํ•œ๋‹˜์˜ ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ ๊ฐ•์˜๋ฅผ ์š”์•ฝํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

Spring

Spring Documentaion

  • Required

    • Spring Framework

    • Spring Boot

  • Optional

    • Spring Data

    • Spring Session

    • Spring Security

    • Spring Rest Docs

    • Spring Batch

    • Spring Cloud


์ข‹์€ ๊ฐ์ฒด์ง€ํ–ฅ์˜ 5๊ฐ€์ง€ ์›์น™ (SOLID)

SRP: ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(single responsibility principle)

  • ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ ์ฑ…์ž„๋งŒ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.

  • ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌ์‹œ์ผœ ๋ณ€๊ฒฝ์ด ์žˆ์„ ๋•Œ ํŒŒ๊ธ‰ ํšจ๊ณผ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ ๊ฐ์ฒด๋Š” ์‹คํ–‰ํ•˜๋Š” ์ฑ…์ž„๋งŒ ๋‹ด๋‹น

DIP: ์˜์กด๊ด€๊ณ„ ์—ญ์ „ ์›์น™ (Dependency inversion principle)

  • ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” โ€œ์ถ”์ƒํ™”์— ์˜์กดํ•ด์•ผ์ง€, ๊ตฌ์ฒดํ™”์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค.โ€

  • ๊ตฌํ˜„ ํด๋ž˜์Šค์— ์˜์กดํ•˜์ง€ ๋ง๊ณ , ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋ผ.

  • ์—ญํ• (Interface)์— ์˜์กดํ•ด์•ผ ๊ตฌํ˜„์˜ ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

  • ์˜์กด์„ฑ ์ฃผ์ž…(DI)์€ DIP ์›์น™์„ ๋”ฐ๋ฆ„

OCP: ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™ (Open/closed principle)

  • ์†Œํ”„ํŠธ์›จ์–ด ์š”์†Œ๋Š” ํ™•์žฅ์—์„œ๋Š” ์—ด๋ ค ์žˆ์œผ๋‚˜ ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉ ์˜์—ญ๊ณผ ๊ตฌ์„ฑ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆ”

  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค์— ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด ์‚ฌ์šฉ ์—ญ์˜์˜ ๋ณ€๊ฒฝ์„ ๋‹ซ์„ ์ˆ˜ ์žˆ๋‹ค.

LSP: ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™ (Liskov substitution principle)

  • ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ์ฒด๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ์ •ํ™•์„ฑ์„ ๊นจ๋œจ๋ฆฌ์ง€ ์•Š์œผ๋ฉด์„œ ํ•˜์œ„ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

  • ๋‹คํ˜•์„ฑ์—์„œ ํ•˜์œ„ ํด๋ž˜์Šค๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๊ทœ์•ฝ์„ ๋‹ค ์ง€์ผœ์•ผ ํ•œ๋‹ค.

ISP: ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™ (Interface segregation principle)

  • ํŠน์ • ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ๋ฒ”์šฉ ์ธํ„ฐํŽ˜์ด์Šค ํ•˜๋‚˜๋ณด๋‹ค ๋‚ซ๋‹ค.

  • ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ถ„๋ฆฌ๋กœ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋ช…ํ™•ํ•ด์ง€๊ณ , ๋Œ€์ฒด ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง„๋‹ค.

์Šคํ”„๋ง๊ณผ ๊ฐ์ฒด์ง€ํ–ฅ

IoC(Inversion of Control, ์ œ์–ด์˜ ์—ญ์ „)

  • ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์„ ์ง์ ‘ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์™ธ๋ถ€์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ

DI(Dependency Injection, ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…)

  • ์˜์กด๊ด€๊ณ„๋Š” ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด ๊ด€๊ณ„์™€, ์‹คํ–‰ ์‹œ์ ์— ๊ฒฐ์ •๋˜๋Š” ๋™์ ์ธ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค) ์˜์กด ๊ด€๊ณ„ ๋‘˜์„ ๋ถ„๋ฆฌํ•ด์„œ ์ƒ๊ฐ

  • ์Šคํ”„๋ง์ด ๋‹คํ˜•์„ฑ + OCP(๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™), DIP(์˜์กด๊ด€๊ณ„ ์—ญ์ „ ์›์น™) ๊ฐ€๋Šฅํ•˜๋„๋ก ์ง€์›

  • ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„

    • ํด๋ž˜์Šค๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” import ์ฝ”๋“œ๋งŒ ๋ณด๊ณ  ์˜์กด๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ํŒ๋‹จ

  • ๋™์ ์ธ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ์˜์กด ๊ด€๊ณ„

    • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ์ ์— ์‹ค์ œ ์ƒ์„ฑ๋œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์˜์กด ๊ด€๊ณ„

  • ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ˜ธ์ถœํ•˜๋Š” ๋Œ€์ƒ์˜ ํƒ€์ž… ์ธ์Šคํ„ด์Šค ์˜์กด๊ด€๊ณ„ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

DI Container(IoC Container)

  • ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋ฉด์„œ ์˜์กด๊ด€๊ณ„๋ฅผ ์—ฐ๊ฒฐํ•ด ์ฃผ๋Š” ๊ฒƒ์„ ์˜๋ฏธ

  • ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์— ์ดˆ์ ์„ ๋งž์ถ”๋ฉด DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š”๊ฒŒ ์ ํ•ฉ

์Šคํ”„๋ง์€ DI, DI Container๋กœ ๋‹คํ˜•์„ฑ + OCP, DIP์„ ์ ์šฉ์‹œ์ผœ ํด๋ผ์ด์–ธํŠธ์˜ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด ๊ธฐ๋Šฅ ํ™•์žฅ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์ง€์›


๋„๋ฉ”์ธ ์„ค๊ณ„

  • ๋„๋ฉ”์ธ ํ˜‘๋ ฅ, ์—ญํ• , ์ฑ…์ž„ ๊ด€๊ณ„ (๊ธฐํš์ž ์‹œ์ )

    • ์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ๋„๋กœ ์„ค๊ณ„

  • ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ (๊ฐœ๋ฐœ์ž ์‹œ์ )

  • ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ (์ธ์Šคํ„ด์Šค๋ผ๋ฆฌ์˜ ์ฐธ์กฐ)

Spring Container

/** 
 * AnnotationConfigApplicationContext : ApplicationContext ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด
 *  ConfigObject : ๊ตฌ์„ฑ ์ •๋ณด
 */
ApplicationContext applicationContext = 
  new AnnotationConfigApplicationContext(ConfigObject.class);
  • ApplicationContext = ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” XML ๊ธฐ๋ฐ˜ ๋˜๋Š” ์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ์ž๋ฐ” ์„ค์ • ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ ๊ณผ์ •

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ

    • @Configuration ์„ ์–ธ ๊ฐ์ฒด๋ฅผ ์„ค์ • ์ •๋ณด๋กœ ์‚ฌ์šฉ

    • ๋˜๋Š” new AnnotationConfigApplicationContext(ConfigObject.class)

  • ์Šคํ”„๋ง ๋นˆ ๋“ฑ๋ก

    • Config ๊ฐ์ฒด์—์„œ @Bean ์„ ์–ธ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ํ˜ธ์ถœํ•ด์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก

    • ์Šคํ”„๋ง ๋นˆ(์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๊ฐ์ฒด)์€ @Bean ์„ ์–ธ๋œ ๋ฉ”์„œ๋“œ๋ช…์„ ์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ @Bean(name="beanName") ์ฒ˜๋Ÿผ ์ง์ ‘ ๋ถ€์—ฌ๋„ ๊ฐ€๋Šฅ

    • ๋นˆ ์ด๋ฆ„์€ ํ•ญ์ƒ ๋‹ค๋ฅธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์ž.

      • ๊ฐ™์€ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋‹ค๋ฅธ ๋นˆ์ด ๋ฌด์‹œ๋˜๊ฑฐ๋‚˜, ๋ฎ์–ด์“ฐ์ด๊ฑฐ๋‚˜ ์„ค์ •์— ๋”ฐ๋ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ

  • ์Šคํ”„๋ง ๋นˆ ์˜์กด๊ด€๊ณ„ ์„ค์ •

    • ์„ค์ • ์ •๋ณด๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…(DI)

Bean ์กฐํšŒ

AnnotationConfigApplicationContext ac = 
  new AnnotationConfigApplicationContext(AppConfig.class);

@Test
void findAllBean() {
    // ์Šคํ”„๋ง์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ๋นˆ ์ •๋ณด ์กฐํšŒ
    String[] beanDefinitionNames = ac.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {
        // ๋นˆ ์ด๋ฆ„์œผ๋กœ ๋นˆ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค) ์กฐํšŒ
        Object bean = ac.getBean(beanDefinitionName);
        System.out.println("name=" + beanDefinitionName + " object=" +
        bean);
    }
}

@Test
void findApplicationBean() {
    String[] beanDefinitionNames = ac.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {
        BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
        // ROLE_APPLICATION: ์ง์ ‘ ๋“ฑ๋กํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นˆ
        // ROLE_INFRASTRUCTURE: ์Šคํ”„๋ง์ด ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋นˆ
        if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
        Object bean = ac.getBean(beanDefinitionName);
        System.out.println("name=" + beanDefinitionName + " object=" +
        bean);
        }
    }
}

๋นˆ ์กฐํšŒ ๋ฐฉ๋ฒ•

  • ๋นˆ ์ด๋ฆ„๊ณผ ํƒ€์ž…์œผ๋กœ ์กฐํšŒ: ac.getBean(๋นˆ์ด๋ฆ„, ํƒ€์ž…)

  • ํ•ด๋‹น ํƒ€์ž…์˜ ๋ชจ๋“  ๋นˆ ์กฐํšŒ: ac.getBeansOfType()

  • ์กฐํšŒ ๋Œ€์ƒ ์Šคํ”„๋ง ๋นˆ์ด ์—†์œผ๋ฉด ์˜ˆ์™ธ ๋ฐœ์ƒ

    • NoSuchBeanDefinitionException: No bean named 'xxxxx' available

BeanFactory

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ตœ์ƒ์œ„ ์ธํ„ฐํŽ˜์ด์Šค

  • ์Šคํ”„๋ง ๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ์—ญํ•  ๋‹ด๋‹น(getBean() ์ œ๊ณต)

BeanFactory <- ApplicationContext <- AnnotationConfig, ApplicationContext

ApplicationContext

  • BeanFactory ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์ƒ์†๋ฐ›์•„์„œ ์ œ๊ณต

  • ๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ธฐ๋Šฅ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์ˆ˜ ๋งŽ์€ ํŽธ๋ฆฌ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ ์ œ๊ณต

    • MessageSource

      • ๋ฉ”์‹œ์ง€์†Œ์Šค๋ฅผ ํ™œ์šฉํ•œ ๊ตญ์ œํ™” ๊ธฐ

      • ํ•œ๊ตญ์—์„œ ๋“ค์–ด์˜ค๋ฉด ํ•œ๊ตญ์–ด, ์˜์–ด๊ถŒ์—์„œ ๋“ค์–ด์˜ค๋ฉด ์˜์–ด ์ถœ๋ ฅ

    • EnvironmentCapable

      • ํ™˜๊ฒฝ๋ณ€์ˆ˜

      • ๋กœ์ปฌ, ๊ฐœ๋ฐœ, ์šด์˜๋“ฑ์„ ๊ตฌ๋ถ„ํ•ด์„œ ์ฒ˜๋ฆฌ

    • ApplicationEventPublisher

      • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฒคํŠธ

      • ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๊ณ  ๊ตฌ๋…ํ•˜๋Š” ๋ชจ๋ธ์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ง€์›

    • ResourceLoader

      • ํŽธ๋ฆฌํ•œ ๋ฆฌ์†Œ์Šค ์กฐํšŒ

      • ํŒŒ์ผ, ํด๋ž˜์ŠคํŒจ์Šค, ์™ธ๋ถ€ ๋“ฑ์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒ

BeanDefinition

  • ์Šคํ”„๋ง ๋นˆ ์„ค์ • ๋ฉ”ํƒ€ ์ •๋ณด

    • @Bean, <bean> ๊ฐ ํ•˜๋‚˜์”ฉ ๋ฉ”ํƒ€ ์ •๋ณด ์ƒ์„ฑ

  • ์ถ”์ƒํ™”๋œ BeanDefinition ๋•๋ถ„์— ์Šคํ”„๋ง์ด (์ž๋ฐ” ์ฝ”๋“œ, XML, Groovy ๋“ฑ)๋‹ค์–‘ํ•œ ์„ค์ • ํ˜•์‹์„ ์ง€์›

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์ด ๋ฉ”ํƒ€์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์Šคํ”„๋ง ๋นˆ ์ƒ์„ฑ

Singleton Container

Singleton Pattern

  • ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋”ฑ ํ•œ๊ฐœ๋งŒ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด

  • ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๋‘ ๊ฐœ ์ด์ƒ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ•˜๋„๋ก private ์ƒ์„ฑ์ž ์‚ฌ์šฉ

  • ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด๋ฅผ ๊ณต์œ  ํ•ด์„œ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ˆ˜ ๋งŽ์€ ๋ฌธ์ œ์  ๋ณด์œ 

    • ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ์Œ.

    • ์˜์กด๊ด€๊ณ„์ƒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กด(DIP๋ฅผ ์œ„๋ฐ˜).

    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•ด์„œ OCP ์›์น™์„ ์œ„๋ฐ˜ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ.

    • ํ…Œ์ŠคํŠธ์˜ ์–ด๋ ค์›€.

    • ๋‚ด๋ถ€ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ดˆ๊ธฐํ™” ํ•˜๊ธฐ ์–ด๋ ค์›€.

    • private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋‹ˆ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์–ด๋ ค์›€

    • ๊ฒฐ๋ก ์ ์œผ๋กœ ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง€๊ณ , ์•ˆํ‹ฐํŒจํ„ด์œผ๋กœ ๋ถˆ๋ฆฌ์›€.

Singleton Container

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ: ์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ ์—ญํ• 

์‹ฑ๊ธ€ํ†ค ๋ ˆ์ง€์ŠคํŠธ: ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ

  • ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๋ฉด์„œ, ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌ

    • DIP, OCP, ํ…Œ์ŠคํŠธ, private ์ƒ์„ฑ์ž๋กœ ๋ถ€ํ„ฐ ์ž์œ ๋กœ์›€

  • ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด(์Šคํ”„๋ง ๋นˆ)๋Š” ์ƒํƒœ๋ฅผ ๋ฌด์ƒํƒœ(stateless)๋กœ ์„ค๊ณ„ํ•ด์•ผ ํ•œ๋‹ค.

    • ํŠน์ • ํด๋ผ์ด์–ธํŠธ์— ์˜์กด์ ์ธ ํ•„๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์•ˆ๋œ๋‹ค.

    • ํŠน์ • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ํ•„๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์•ˆ๋œ๋‹ค.

    • ๊ฐ€๊ธ‰์ ์œผ๋กœ ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.

    • ํ•„๋“œ ๋Œ€์‹ ์— ์ž๋ฐ”์—์„œ ๊ณต์œ ๋˜์ง€ ์•Š๋Š” ์ง€์—ญ๋ณ€์ˆ˜, ํŒŒ๋ผ๋ฏธํ„ฐ, ThreadLocal ๋“ฑ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

  • ์Šคํ”„๋ง ์„ค์ • ์ •๋ณด๋Š” ํ•ญ์ƒ @Configuration์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅํ•˜์ž.

    • @Configuration ์„ ์–ธ ์‹œ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” CGLIB ๊ธฐ์ˆ ์ด ์ ์šฉ๋˜์–ด ์‹ฑ๊ธ€ํ†ค ๋ณด์žฅ

    • ์„ค์ • ์ •๋ณด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ xxx@CGLIB ํด๋ž˜์Šค๊ฐ€ ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅ

Component Scan

  • ์„ค์ • ์ •๋ณด ํด๋ž˜์Šค์— @ComponentScan์„ ๋ช…์‹œํ•ด ์ฃผ๋ฉด, ์ž๋™์œผ๋กœ class path๋ฅผ ํƒ์ƒ‰ํ•ด์„œ @Component๊ฐ€ ๋ช…์‹œ๋œ class๋“ค์„ ์Šค์บ”ํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก

    • ๋นˆ ์ด๋ฆ„ ๊ธฐ๋ณธ ์ „๋žต: ์•ž๊ธ€์ž๋งŒ ์†Œ๋ฌธ์ž๋กœ ๋ณ€๊ฒฝ๋œ ํด๋ž˜์Šค๋ช…์„ ์‚ฌ์šฉ

    • ๋นˆ ์ด๋ฆ„ ์ง์ ‘ ์ง€์ •: @Component("beanName")

  • ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์€ @Autowired๊ฐ€ ํ•ด๊ฒฐ

    • ๊ธฐ๋ณธ ์กฐํšŒ ์ „๋žต: ํƒ€์ž…์ด ๊ฐ™์€ ๋นˆ์„ ์ฐพ์•„์„œ ์ฃผ์ž…

@ComponentScan(
  /**
   * basePackages
   * ํƒ์ƒ‰ํ•  ํŒจํ‚ค์ง€์˜ ์‹œ์ž‘ ์œ„์น˜(ํ•˜์œ„ ํŒจํ‚ค์ง€ ๋ชจ๋‘ ํƒ์ƒ‰)
   * ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด @ComponentScan ์„ ์–ธ๋œ ์„ค์ • ์ •๋ณด ํด๋ž˜์Šค์˜ ํŒจํ‚ค์ง€๊ฐ€ ์‹œ์ž‘ ์œ„์น˜
   * ์„ค์ • ์ •๋ณด ํด๋ž˜์Šค์˜ ์œ„์น˜๋ฅผ ํ”„๋กœ์ ํŠธ ์ตœ์ƒ ๋‹จ์— ๋‘๋Š” ๊ฒƒ์„ ์ถ”์ฒœ
   * 
   * ์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ๊ธฐ๋ณธ ๋ฐฉ๋ฒ•์œผ๋กœ @SpringBootApplication ์— @ComponentScan ํฌํ•จ
   */
    basePackages = {"hello.core", "hello.service"}, 
}
  • Component Scan ๊ธฐ๋ณธ ๋Œ€์ƒ

    • @Component: ์ปดํฌ๋„ŒํŠธ ์Šค์บ” ํƒ์ƒ‰ ๋Œ€์ƒ

    • @Controller : ์Šคํ”„๋ง MVC ์ปจํŠธ๋กค๋Ÿฌ

    • @Service : ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ณ„์ธต

    • @Repository : ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต(๋ฐ์ดํ„ฐ ๊ณ„์ธต์˜ ์˜ˆ์™ธ๋ฅผ ์Šคํ”„๋ง ์˜ˆ์™ธ๋กœ ๋ณ€ํ™˜)

    • @Configuration : ์Šคํ”„๋ง ์„ค์ • ์ •๋ณด(์Šคํ”„๋ง ๋นˆ์ด ์‹ฑ๊ธ€ํ†ค์„ ์œ ์ง€ํ•˜๋„๋ก ์ฒ˜๋ฆฌ)

Filters

  • includeFilters : ์ปดํฌ๋„ŒํŠธ ์Šค์บ” ๋Œ€์ƒ ์ถ”๊ฐ€ ์ง€์ •

  • excludeFilters : ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์—์„œ ์ œ์™ธํ•  ๋Œ€์ƒ ์ง€์ •

@ComponentScan(
    includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
    excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class)
)

์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…

  • ์ƒ์„ฑ์ž ์ฃผ์ž… โญ๏ธ

    • ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์˜์กด ๊ด€๊ณ„๋ฅผ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ๋ฒ•

    • ๋”ฑ 1๋ฒˆ ํ˜ธ์ถœ ๋ณด์žฅ. ๋ถˆ๋ณ€-ํ•„์ˆ˜ ์˜์กด๊ด€๊ณ„

    • ๋ถˆ๋ณ€ํ•˜๊ฒŒ ์„ค๊ณ„ ๊ฐ€๋Šฅํ•˜๊ณ , ์˜์กด๊ด€๊ณ„ ๋ˆ„๋ฝ ๋ฐฉ์ง€(final)

    • ํ•ญ์ƒ ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์„ ํƒํ•˜์ž.

    • lombok ์‚ฌ์šฉ ์‹œ @RequiredArgsConstructor

    @Component
    public class OrderServiceImpl implements OrderService {
    
      private final MemberRepository memberRepository;
      private final DiscountPolicy discountPolicy;
    
      @Autowired
      public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
          this.memberRepository = memberRepository;
          this.discountPolicy = discountPolicy;
      }
    }
  • ์ˆ˜์ •์ž ์ฃผ์ž…(Setter)

    • ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…

    • ์„ ํƒ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์˜์กด ๊ด€๊ณ„

      • ์„ ํƒ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ(์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์–ด๋„ ๋™์ž‘ํ•˜๋„๋ก ํ•  ๊ฒฝ์šฐ)

        • @Autowired(required = false)

      • ๋‹จ, ์ค‘๊ฐ„์— ์˜์กด๊ด€๊ณ„๋ฅผ ๋ณ€๊ฒฝํ•  ์ผ์€ ๊ฑฐ์˜ ์—†์Œ

    @Component
    public class OrderServiceImpl implements OrderService {
    
      private MemberRepository memberRepository;
      private DiscountPolicy discountPolicy;
    
      @Autowired
      public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
      }
    
      @Autowired
      public void setDiscountPolicy(DiscountPolicy discountPolicy) {
        this.discountPolicy = discountPolicy;
      }
    }
  • ํ•„๋“œ ์ฃผ์ž…

    • ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ํž˜๋“ค๋‹ค๋Š” ์น˜๋ช…์ 

    • ๊ฐ€๊ธ‰์  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ๋งŒ ์‚ฌ์šฉ

    @Component
    public class OrderServiceImpl implements OrderService {
    
        @Autowired private MemberRepository memberRepository;
    
        @Autowired private DiscountPolicy discountPolicy;
    }
  • ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ์ฃผ์ž…

    • ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ฃผ์ž…

    • ํ•œ๋ฒˆ์— ์—ฌ๋Ÿฌ ํ•„๋“œ๋ฅผ ์ฃผ์ž… ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ํŠน์ง•์ด ์žˆ์ง€๋งŒ ์ž˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

    @Component
    public class OrderServiceImpl implements OrderService {
    
      private MemberRepository memberRepository;
      private DiscountPolicy discountPolicy;
    
      @Autowired
      public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
      }
    }

์˜ต์…˜

  • @Autowired(required=false)

    • ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ์ž์ฒด๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Œ

    @Autowired(required = false)
    public void setNoBean1(Member member) {
        System.out.println("setNoBean1 = " + member);
    }
  • org.springframework.lang.@Nullable

    • ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด null

    @Autowired
    public void setNoBean2(@Nullable Member member) {
        System.out.println("setNoBean2 = " + member);
    }
  • Optional<>

    • ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด Optional.empty

    @Autowired(required = false)
    public void setNoBean3(Optional<Member> member) {
        System.out.println("setNoBean3 = " + member);
    }

์กฐํšŒ ๋Œ€์ƒ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ผ ๊ฒฝ์šฐ

@Autowired

  • ํƒ€์ž… ๋งค์นญ์„ ์‹œ๋„

  • ์—ฌ๋Ÿฌ ๋นˆ์ด ์กฐํšŒ๋˜๋ฉด ํ•„๋“œ ์ด๋ฆ„, ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์œผ๋กœ ๋นˆ ์ด๋ฆ„์„ ์ถ”๊ฐ€ ๋งค์นญ

@Autowired
private DiscountPolicy rateDiscountPolicy

@Qualifier

  • ๋นˆ ๋“ฑ๋ก ์‹œ @Qualifier ๋กœ ์ถ”๊ฐ€ ๊ตฌ๋ถ„์ž ์„ค์ •

  • @Qualifier ๋งค์นญ โžœ ๋นˆ ์ด๋ฆ„ ๋งค์นญ โžœ NoSuchBeanDefinitionException ์˜ˆ์™ธ

@Component
@Qualifier("mainDiscountPolicy") // ๋นˆ ๋“ฑ๋ก ์‹œ ์ด๋ฆ„ ์„ค์ •
public class RateDiscountPolicy implements DiscountPolicy {}

/** 1. ์ƒ์„ฑ์ž ์ž๋™ ์ฃผ์ž…์˜ ๊ฒฝ์šฐ **/
@Autowired
public OrderServiceImpl(
        MemberRepository memberRepository,
        @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {

  this.memberRepository = memberRepository;
  this.discountPolicy = discountPolicy;

}

/** 2. ์ˆ˜์ •์ž ์ž๋™ ์ฃผ์ž…์˜ ๊ฒฝ์šฐ **/
@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
  return discountPolicy;
}

@Primary

  • @Autowired ์‹œ์— ์—ฌ๋Ÿฌ ๋นˆ์ด ๋งค์นญ๋˜๋ฉด @Primary๊ฐ€ ์šฐ์„ ๊ถŒ

  • Database Connection์„ ๊ฐ€์ ธ์˜ฌ ๊ฒฝ์šฐ ๋“ฑ ์€๊ทผ ์‚ฌ์šฉ

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}

์ฐธ๊ณ . ๋นˆ ์• ๋…ธํ…Œ์ด์…˜ ๋งŒ๋“ค๊ธฐ

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}

//

@Component
@MainDiscountPolicy
public class RateDiscountPolicy implements DiscountPolicy {}

//

@Autowired
public OrderServiceImpl(
          MemberRepository memberRepository,
          @MainDiscountPolicy DiscountPolicy discountPolicy) {
  this.memberRepository = memberRepository;
  this.discountPolicy = discountPolicy;
}

์กฐํšŒํ•œ ๋นˆ์ด ๋ชจ๋‘ ํ•„์š”ํ•  ๊ฒฝ์šฐ

๋™์ ์œผ๋กœ Bean์„ ์„ ํƒํ•ด์•ผํ•  ๋•Œ, ๋‹คํ˜•์„ฑ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ Bean์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

public class AllBeanTest {

    @Test
    void findAllBean() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);

        DiscountService discountService = ac.getBean(DiscountService.class);
        Member member = new Member(1L, "userA", Grade.VIP);
        int discountPrice = discountService.discount(member, 10000, "fixDiscountPolicy");

        assertThat(discountService).isInstanceOf(DiscountService.class);
        assertThat(discountPrice).isEqualTo(1000);

        int rateDiscountPrice = discountService.discount(member, 20000, "rateDiscountPolicy");
        assertThat(rateDiscountPrice).isEqualTo(2000);
    }


    static class DiscountService {
        /**
         * Map(Key=์Šคํ”„๋ง ๋นˆ ์ด๋ฆ„, value=DiscountPolicy ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•œ ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ)
         * 
         * policyMap
         * {key = "fixDiscountPolicy", value = {FixDiscountPolicy@5731}}
         * {key = "rateDiscountPolicy", value = {RateDiscountPolicy@5732}}
         */
        private final Map<String, DiscountPolicy> policyMap;
        /**
         * DiscountPolicy ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•œ ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ์„
         *
         * policies
         *  0 = {FixDiscountPolicy@5736} discountFixAmount = 1000
         *  1 = {RateDiscountPolicy@5737} discountPercent = 10
         */
        private final List<DiscountPolicy> policies;

        public DiscountService(Map<String, DiscountPolicy> policyMap,  List<DiscountPolicy> policies) {
            this.policyMap = policyMap;
            this.policies = policies;
        }

        // ์›ํ•˜๋Š” ํ• ์ธ ๋ฐฉ๋ฒ•์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ํ›„, Map์—์„œ ๊บผ๋‚ด์„œ ์‚ฌ์šฉ
        public int discount(Member member, int price, String discountCode) {
            DiscountPolicy discountPolicy = policyMap.get(discountCode);
            return discountPolicy.discount(member, price);
        }
    }
}

ํŽธ๋ฆฌํ•œ ์ž๋™ ๋นˆ ๋“ฑ๋ก ๊ธฐ๋Šฅ์„ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•˜์ž.

์ˆ˜๋™ ๋นˆ ๋“ฑ๋ก์€ ๊ธฐ์ˆ  ์ง€์› ๊ฐ์ฒด, ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•˜๋Š”(Bean Map, List) ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ ์šฉํ•ด๋ณด์ž.

์ง์ ‘ ๋“ฑ๋กํ•˜๋Š” ๋นˆ์€ ์„ค์ • ์ •๋ณด์— ๋ฐ”๋กœ ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์ข‹๋‹ค.

๋นˆ ์ƒ์„ฑ์ฃผ๊ธฐ ์ฝœ๋ฐฑ

์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฒคํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ โžœ ์Šคํ”„๋ง ๋นˆ ์ƒ์„ฑ โžœ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… โžœ ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ โžœ ์‚ฌ์šฉ โžœ ์†Œ๋ฉธ์ „ ์ฝœ๋ฐฑ โžœ ์Šคํ”„๋ง ์ข…๋ฃŒ

.

๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ์ดˆ๊ธฐํ™”๋ฅผ ๋ถ„๋ฆฌํ•˜์ž.

  • ์ƒ์„ฑ์ž๋Š” ๊ฐ์ฒด ์ƒ์„ฑ์— ์ฑ…์ž„์„, ์ดˆ๊ธฐํ™”๋Š” ์ƒ์„ฑ๋œ ๊ฐ’๋“ค์„ ํ™œ์šฉํ•ด์„œ ์ปค๋„ฅ์…˜ ์—ด๊ฒฐ๊ณผ ๊ฐ™์€ ๋ฌด๊ฑฐ์šด ๋™์ž‘์„ ์ˆ˜ํ–‰

  • ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„๊ณผ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ์œ ์ง€๋ณด์ˆ˜ ๊ด€์ ์—์„œ ์ข‹์Œ

.

์Šคํ”„๋ง์˜ ๋นˆ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ ์ง€์› ๋ฐฉ๋ฒ•

@PostConstruct, @PreDestory ์ง€์›

  • ์Šคํ”„๋ง์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•

  • ๋ฉ”์„œ๋“œ์— ์• ๋„ˆํ…Œ์ด์…˜๋งŒ ์„ ์–ธํ•˜๋ฉด ๋˜๋Š” ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•

  • ์Šคํ”„๋ง์— ์ข…์†์กฑ์ด์ง€ ์•Š์€ ๊ธฐ์ˆ 

  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ ์šฉ ๋ถˆ๊ฐ€(@Bean ์„ค์ •์ •๋ณด ๊ธฐ๋Šฅ ํ™œ์šฉ)

์„ค์ • ์ •๋ณด์— ์ดˆ๊ธฐํ™”/์ข…๋ฃŒ ๋ฉ”์„œ๋“œ ์ง€์ •

  • @Bean(initMethod = "init", destroyMethod = "close")

  • destroyMethod ๊ธฐ๋ณธ๊ฐ’์ด inferred(์ถ”๋ก )์œผ๋กœ ๋“ฑ๋ก

    • close, shutdown(๋Œ€๋ถ€๋ถ„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ฐ€์ง€๋Š” ์ข…๋ฃŒ ๋ฉ”์„œ๋“œ ์ด๋ฆ„) ๋ฉ”์„œ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ

  • ๋ฉ”์„œ๋“œ ์ด๋ฆ„์˜ ์ž์œ ๋กœ์›€

  • ์Šคํ”„๋ง ๋นˆ์ด ์Šคํ”„๋ง ์ฝ”๋“œ์— ์˜์กดํ•˜์ง€ ์•Š์Œ

  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—๋„ ์ ์šฉ ๊ฐ€๋Šฅ(์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ์„ค์ • ์ •๋ณด๋ฅผ ์‚ฌ์šฉ)

InitializingBean, DisposableBean ์ธํ„ฐํŽ˜์ด์Šค

  • InitializingBean.afterPropertiesSet()

  • DisposableBean.destroy()

  • ์ง€๊ธˆ์€ ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฐฉ๋ฒ•

    • ์Šคํ”„๋ง ์ „์šฉ ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กด

    • ์ดˆ๊ธฐํ™”, ์†Œ๋ฉธ ๋ฉ”์„œ๋“œ ์ด๋ฆ„ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€

    • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ ์šฉ ๋ถˆ๊ฐ€

๋นˆ ์Šค์ฝ”ํ”„

๋นˆ์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„

์Šคํ”„๋ง์€ ์‹ฑ๊ธ€ํ†ค, ํ”„๋กœํ† ํƒ€์ž…, ์›น ๊ด€๋ จ ์Šค์ฝ”ํ”„(request, session, application)๋ฅผ ์ง€์›

๋นˆ ์Šค์ฝ”ํ”„ ์ง€์ • ๋ฐฉ๋ฒ•

// ์ปดํฌ๋„ŒํŠธ ์Šค์บ” ์ž๋™ ๋“ฑ๋ก
@Scope("prototype")
@Component
public class HelloBean {}

...

// ์ˆ˜๋™ ๋“ฑ๋ก
@Scope("prototype")
@Bean
PrototypeBean HelloBean() {
    return new HelloBean();
}

.

์‹ฑ๊ธ€ํ†ค

  • ๊ธฐ๋ณธ ์Šค์ฝ”ํ”„

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘~์ข…๋ฃŒ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ๊ฐ€์žฅ ๋„“์€ ๋ฒ”์œ„์˜ ์Šค์ฝ”ํ”„

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํ•ญ์ƒ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค์˜ ์Šคํ”„๋ง ๋นˆ์„ ๋ฐ˜ํ™˜

.

ํ”„๋กœํ† ํƒ€์ž…

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์˜ ์ƒ์„ฑ๊ณผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…, ์ดˆ๊ธฐํ™”๊นŒ์ง€๋งŒ ๊ด€์—ฌํ•˜๋Š” ๋งค์šฐ ์งง์€ ๋ฒ”์œ„์˜ ์Šค์ฝ”ํ”„(์ข…๋ฃŒ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ X)

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์กฐํšŒํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฐ˜ํ™˜

    • ์˜์กด์„ฑ ์ฃผ์ž…์„ ๋ฐ›๋Š” ์‹œ์ ์— ๊ฐ๊ฐ ์ƒˆ๋กœ์šด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์ด ์ƒ์„ฑ

  • ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์กฐํšŒํ•œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ด€๋ฆฌ. ์ข…๋ฃŒ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ˆ˜ํ–‰

  • ์ง์ ‘์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ผ์€ ๋งค์šฐ ๋“œ๋ฌพ

์ฐธ๊ณ . ์‹ฑ๊ธ€ํ†ค ๋นˆ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ์‹œ ๋ฌธ์ œ์ 

  • ์Šคํ”„๋ง์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค ๋นˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ฑ๊ธ€ํ†ค ๋นˆ์ด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์‚ฌ์šฉ

  • ์‹ฑ๊ธ€ํ†ค ๋นˆ์€ ์ƒ์„ฑ ์‹œ์ ์—๋งŒ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๋ฐ›์œผ๋ฏ€๋กœ, ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ ์žํ•˜๋Š” ์˜๋„์™€ ๋‹ค๋ฅด๊ฒŒ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ ์Šค์ฝ”ํ”„๊ฐ€ ์‹ฑ๊ธ€ํ†ค ๋นˆ๊ณผ ํ•จ๊ป˜ ๊ณ„์† ์œ ์ง€

  • ObjectProvider ์„ ํ™œ์šฉํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐ

    • ์ง€์ •ํ•œ ๋นˆ์„ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋Œ€์‹  ์ฐพ์•„์ฃผ๋Š” DL(Dependency Lookup) ์„œ๋น„์Šค ์ œ๊ณต

@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;

public int logic() {
    PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
    prototypeBean.addCount();
    int count = prototypeBean.getCount();
    return count;
}

.

์›น ์Šค์ฝ”ํ”„

  • ์›น ํ™˜๊ฒฝ์—์„œ๋งŒ ๋™์ž‘

  • ํ”„๋กœํ† ํƒ€์ž… ๋นˆ๊ณผ ๋‹ค๋ฅด๊ฒŒ ์Šคํ”„๋ง์ด ํ•ด๋‹น ์Šค์ฝ”ํ”„์˜ ์ข…๋ฃŒ์‹œ์ ๊นŒ์ง€ ๊ด€๋ฆฌ

  • ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ณณ์—๋งŒ ์ตœ์†Œํ™”ํ•ด์„œ ์‚ฌ์šฉ ๊ถŒ์žฅ

request:

  • HTTP ์š”์ฒญ ํ•˜๋‚˜๊ฐ€ ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐˆ ๋•Œ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„

  • ๊ฐ๊ฐ์˜ HTTP ์š”์ฒญ๋งˆ๋‹ค ๋ณ„๋„์˜ ๋นˆ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ/๊ด€๋ฆฌ

/**
 * @Scope
 * - ์‹ค์ œ ๊ณ ๊ฐ ์š”์ฒญ์ด ๋“ค์–ด์™€์•ผ request ์Šค์ฝ”ํ”„ ๊ฐ์ฒด์˜ ๋นˆ์ด ์ƒ์„ฑ๋˜๋ฏ€๋กœ ๋นˆ ์ƒ์„ฑ ์ง€์—ฐ์ด ํ•„์š”.
 * - ์ ์šฉ ๋Œ€์ƒ์— ๋”ฐ๋ผ ScopedProxyMode.TARGET_CLASS, ScopedProxyMode.INTERFACES ์„ ํƒ
 * 
 * - HTTP request์™€ ๊ด€๊ณ„ ์—†์ด ์‹ฑ๊ธ€ํ†ค์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅธ ๋นˆ์— ๋ฏธ๋ฆฌ ์˜์กด์„ฑ ์ฃผ์ž…
 * - ์š”์ฒญ์ด ์˜ค๋ฉด ํ”„๋ก์‹œ ๊ฐ์ฒด ๋‚ด๋ถ€์—์„œ ์›๋ณธ ๊ฐ์ฒด์„ ์š”์ฒญํ•˜๋Š” ์œ„์ž„ ๋กœ์ง
 */
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {...}

session:

  • HTTP Session๊ณผ ๋™์ผํ•œ ์ƒ๋ช…์ฃผ๊ธฐ(์ƒ์„ฑ~์ข…๋ฃŒ)๋ฅผ ๊ฐ€์ง€๋Š” ์Šค์ฝ”ํ”„

application:

  • ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ(ServletContext)์™€ ๋™์ผํ•œ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๋Š” ์Šค์ฝ”ํ”„

websocket:

  • ์›น ์†Œ์ผ“๊ณผ ๋™์ผํ•œ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๋Š” ์Šค์ฝ”ํ”„

Last updated