[Spring] Bean

GoghΒ·2023λ…„ 1μ›” 2일
0

Spring

λͺ©λ‘ 보기
5/23

🎯 λͺ©ν‘œ : Bean의 이해

πŸ“’ Spring Bean


πŸ“Œ μŠ€ν”„λ§μ—μ„œ 빈?

  • μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ(ApplicationContext)에 μ˜ν•΄ κ΄€λ¦¬λ˜λŠ” 재 μ‚¬μš© μ†Œν”„νŠΈμ›¨μ–΄ μ»΄ν¬λ„ŒνŠΈλ‹€.
  • μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ—μ„œ κ΄€λ¦¬ν•˜λŠ” μΈμŠ€ν„΄μŠ€ν™”λœ 객체λ₯Ό μ˜λ―Έν•˜λ©°, λ‹€μ–‘ν•œ λ°©λ²•μœΌλ‘œ 빈 등둝을 ν• μˆ˜ μžˆλ‹€.
  • @Bean(name = "beanName") 빈 μ΄λ¦„μ˜ 기본값은 λ©”μ†Œλ“œμ΄λ¦„μ„ μ‚¬μš©ν•˜λŠ”λ°, 직접 λΆ€μ—¬ν• μˆ˜ μžˆλ‹€.
/**
 * DIP μœ„λ°˜
 * OrderServiceImpl λŠ” DiscountPolicy μΈν„°νŽ˜μ΄μŠ€ λΏλ§Œμ•„λ‹ˆλΌ
 * RateDiscountPolicy 도 의쑴 ν•˜κ³  μžˆλ‹€.
 * OCP μœ„λ°˜
 * RateDiscountPolicy κ΅¬ν˜„ν•¨μœΌλ‘œμ„œ κΈ°λŠ₯을 ν™•μž₯ν•˜μ˜€λ‹€.
 * κΈ°λŠ₯ ν™•μž₯함과 λ™μ‹œμ— "OrderServiceImpl 클래슀의 μ½”λ“œλ₯Ό λ³€κ²½ν•΄μ•Όν•œλ‹€."
 *     private final DiscountPolicy discountPolicy
 *             = new FixDiscountPolicyImpl();
 *
 * μœ„ 사항듀을 κ°œμ„ ν•˜κΈ° μœ„ν•΄ AppConfig μƒμ„±ν•˜μ—¬ 관심사 뢄리
 * μƒμ„±μž μ£Όμž…μœΌλ‘œ μ „ν™˜ν•˜μ—¬ Service 클래슀 듀은 μΈν„°νŽ˜μ΄μŠ€μ—λ§Œ μ˜μ‘΄ν•˜κ²Œ λœλ‹€.
 */

@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(
                memberRepository(),
                discountPolicy()
        );
    }

    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }

}

πŸ“Œ Bean μ‘°νšŒν•˜κΈ°

  • ApplicationContext의 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ—¬ λ“±λ‘λœ λΉˆμ„ μ‘°νšŒν• μˆ˜ 있으며 빈의 이름, νƒ€μž…, μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„μ²΄ νƒ€μž…μœΌλ‘œ 쑰회 ν• μˆ˜ μžˆλ‹€.
  • λ™μΌν•œ νƒ€μž…μ˜ 빈이 λ‘κ°œ 이상 μ‘΄μž¬ν•œλ‹€λ©΄ 빈의 이름을 μ§€μ •ν•΄μ„œ μ—λŸ¬λ₯Ό 방지 ν• μˆ˜ μžˆλ‹€.
  • μ‘°νšŒν•  빈이 μ—†λ‹€λ©΄ NosuchBeanDefinitionException이 λ°œμƒν•œλ‹€.
class ApplicationContextInfoTest {
    AnnotationConfigApplicationContext ac =
            new AnnotationConfigApplicationContext(AppConfig.class);
    @Test
    @DisplayName("μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 빈 좜λ ₯ν•˜κΈ°")
    void findApplicationBean() {
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition
                    = ac.getBeanDefinition(beanDefinitionName);
                    //Role ROLE_APPLICATION: 직접 λ“±λ‘ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 빈
         	   //Role ROLE_INFRASTRUCTURE: μŠ€ν”„λ§μ΄ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•˜λŠ” 빈
            if (beanDefinition.getRole() == beanDefinition.ROLE_APPLICATION) {
                Object bean = ac.getBean(beanDefinitionName);
                System.out.println(
                        "name = " + beanDefinitionName +
                                " Object = "+ bean);
            }
        }
    }
}
// 좜λ ₯κ°’
name = appConfig Object = hello.core.AppConfig$$EnhancerBySpringCGLIB$$c9c658a0@2371aaca
name = memberService Object = hello.core.member.MemberServiceImpl@5b529706
name = memberRepository Object = hello.core.member.MemoryMemberRepository@63fdab07
name = orderService Object = hello.core.order.OrderServiceImpl@7b5a12ae
name = discountPolicy Object = hello.core.discount.RateDiscountPolicy@5553d0f5
  • 상속 κ΄€κ³„μ˜ λΉˆμ€ λΆ€λͺ¨ νƒ€μž…μ„ 쑰회 ν• λ•Œ, μžμ‹ νƒ€μž…λ„ ν•¨κ»˜ 쑰회 되며, Objectνƒ€μž…μœΌλ‘œ μ‘°νšŒν•˜λ©΄ λͺ¨λ“  μŠ€ν”„λ§ λΉˆμ„ μ‘°νšŒν•˜κ²Œ λœλ‹€.

πŸ“ŒΒ BeanDefinition

  • BeanDefinition은 μŠ€ν”„λ§ 빈의 메타 정보닀.
  • μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 이 메타 정보λ₯Ό λ°”νƒ•μœΌλ‘œ λΉˆμ„ 생성, κ΄€λ¦¬ν•œλ‹€.
  • AnnotationConfigApplicationContext λŠ” AnnotatedBeanDefinitionReader λ₯Ό μ‚¬μš©ν•΄μ„œ AppConfig.class λ₯Ό 읽고 BeanDefinition 을 μƒμ„±ν•œλ‹€.


πŸ“ŒΒ BeanDefinition 정보

  • BeanClassName : 생성할 빈의 클래슀 λͺ…
  • factoryBeanName : νŒ©ν† λ¦¬ μ—­ν• μ˜ λΉˆμ„ μ‚¬μš©ν•  경우 ex) appConfig
  • factoryMethodName : λΉˆμ„ 생성할 νŒ©ν† λ¦¬ λ©”μ†Œλ“œ 지정
  • Scope : κΈ°λ³Έκ°’ - 싱글톀
  • lazyInit : μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλ₯Ό 생성할 λ•Œ λΉˆμ„ μƒμ„±ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, μ‹€μ œ λΉˆμ„ μ‚¬μš©ν•  λ•Œ κΉŒμ§€ μ΅œλŒ€ν•œ 생성을 μ§€μ—°μ²˜λ¦¬ ν•˜λŠ”μ§€ μ—¬λΆ€
  • InitMethodName : λΉˆμ„ μƒμ„±ν•˜κ³  μ˜μ‘΄κ΄€κ³„λ₯Ό μ μš©ν•œ λ’€ ν˜ΈμΆœλ˜λŠ” μ΄ˆκΈ°ν™” λ©”μ†Œλ“œ 이름.
  • DestroyMethodName : 빈의 생λͺ…μ£ΌκΈ°κ°€ λλ‚˜μ„œ μ œκ±°ν•˜κΈ° 직전에 ν˜ΈμΆœλ˜λŠ” λ©”μ†Œλ“œ 이름.
  • Constructor arguments, Properties : μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ—μ„œ μ‚¬μš©ν•œλ‹€.
public class BeanDefinitionTest {
    AnnotationConfigApplicationContext ac = new
            AnnotationConfigApplicationContext(AppConfig.class);
    @Test
    @DisplayName("빈 μ„€μ • 메타정보 확인")
    void findApplicationBean() {
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition =
                    ac.getBeanDefinition(beanDefinitionName);
            if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
                System.out.println("beanDefinitionName" + beanDefinitionName +
                        " beanDefinition = " + beanDefinition);
            }
        }
    }
}
// 좜λ ₯κ°’
beanDefinitionNameappConfig beanDefinition = Generic bean: class [hello.core.AppConfig$$EnhancerBySpringCGLIB$$c9c658a0]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
beanDefinitionNamememberService beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionNamememberRepository beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberRepository; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionNameorderService beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=orderService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionNamediscountPolicy beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=discountPolicy; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
profile
컴퓨터가 할일은 컴퓨터가

0개의 λŒ“κΈ€