BeanFactory 처리 bean 수명 주기 전체 프로 세 스

BeanFactory 의 기본 값 은 Default Listable BeanFactory 입 니 다. 그 중에서 Bean 의 생명 주기 와 방법 은 다음 과 같 습 니 다. 원본 코드 를 참고 하여 같이 보 는 것 을 권장 합 니 다.
1. BeanDefinition 등록 단계 - registerBeanDefinition
이 단 계 는 두 부분 으로 나 뉜 다. 먼저 beanName 을 통 해 BeanDefinition 을 등록 한 다음 에 별명 alias 를 등록 한다.
beanName 으로 등록 하기
처리 과정 은 다음 과 같다.
1. 먼저 BeanDefinition 을 검증 합 니 다. 이 검증 도 등록 과정 에서 마지막 검증 입 니 다. 주로 AbstractBeanDefinition 의 methodOverrides 속성 을 검증 합 니 다.
2. beanName 에 따라 캐 시 에서 BeanDefinition 을 가 져 옵 니 다. 캐 시 에 존재 하 는 경우 allowBeanDefinition Overriding 로고 에 따라 덮어 쓸 수 있 는 지 여 부 를 판단 하고 허용 되면 덮어 씁 니 다. 그렇지 않 으 면 BeanDefinitionStore Exception 이상 을 던 집 니 다.
3. 캐 시 에 beanName 의 BeanDefinition 이 지정 되 어 있 지 않 으 면 현재 단계 에서 Bean 의 생 성 단계 가 시작 되 었 는 지 판단 합 니 다. 그렇다면 beanDefinitionMap 에 잠 금 제어 와 병행 문 제 를 해결 해 야 합 니 다. 그렇지 않 으 면 직접 설정 하면 됩 니 다.
4. 캐 시 에 이 beanName 이나 단일 bean 집합 에 이 beanName 이 존재 하면 호출 합 니 다. resetBeanDefinition() BeanDefinition 캐 시 를 리 셋 합 니 다.
사실 전체 코드 의 핵심 은 this. beanDefinitionMap. put (beanName, beanDefinition) 에 있 습 니 다.
BeanDefinition 의 캐 시 는 신기 한 것 이 아니 라 map, key 를 beanName, value 를 BeanDefinition 으로 정의 합 니 다.
등록 alias
BeanDefinitionRegistry.registerAlias alias 의 등록 을 완료 하고 alias 와 Bean Definition 을 등록 하 는 과정 이 많 지 않 습 니 다.가장 좋 은 곳 에서 호출 되 었 다. checkForAliasCircle() 별명 검 사 를 하 러 왔 습 니 다.
 
2. BeanDefinition 합병 단계 - getMergedBeanDefinition
절 차 는 다음 과 같다.
1. 아버지 빈 데 피 니 션 을 찾 습 니 다. 찾 지 못 하면 자신 을 아버지 빈 데 피 니 션 으로 생각 합 니 다. 찾 으 면 아버지 빈 데 피 니 션 에 아버지 빈 데 피 니 션 이 있 는 지 확인 하고 getMergedBeanDefinition 방법 으로 아버지 빈 데 피 니 션 이 합 병 된 빈 데 피 니 션 을 얻 습 니 다.
2. BeanDefinition 을 합병 하여 부모 BeanDefinition 을 통 해 RootBeanDefinition 대상 을 만 든 다음 에 자식 BeanDefinition 이 부모 BeanDefinition 을 덮어 서 만 든 대상 (덮어 쓰기 속성 같은 것) 을 만 듭 니 다.
3. 합 친 BeanDefinition 을 mergedBeanDefinitions 집합 에 넣 고 마지막 으로 합 친 BeanDefinition 을 되 돌려 줍 니 다.
그 중에서 우 리 는 그 중의 몇 가지 부분 을 주의해 야 한다.
  • 합병 후의 BeanDefinition 은 RootBeanDefinition 으로 받 은 것 입 니 다. 이것 은 RootBeanDefinition 이 아직도 사용 되 고 있 는 이유 입 니 다. 왜냐하면 이것 은 BeanDefinition 을 합병 하 는 작업 에 도 적용 되 기 때 문 입 니 다.
  • 부모 빈 데 피 니 션 이 있 든 없 든 합병 작업 이 발생 할 수 있 으 며, 부모 빈 데 피 니 션 의 합병 이 이 중 에 실 행 될 수 있 음 을 주의해 야 한다.

  •  
    3. Bean 실례 화 전 단계 - resolveBeforeInstantiation
    이 단 계 는 자주 사용 되 지 않 는 작업 입 니 다. 이 단계 에서 우 리 는 하나의 프 록 시 클래스 를 만들어 서 우리 가 생 성 한 인 스 턴 스 를 대체 할 수 있 습 니 다.밑바닥 은 인 스타 그램 AwareBeanPostProcessor 인 터 페 이 스 를 통과 하 는 postProcessBeforeInstantiation 방법 이다.
     
    4. Bean 실례 화 단계 - createBeanInstance
    bean 의 인 스 턴 스 를 만 듭 니 다. 생 성 을 담당 하 는 방법 은 createBeanInstance 입 니 다. 구체 적 인 코드 는 다음 과 같 습 니 다.        
     protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    
                       //   class
    
                       Class> beanClass = resolveBeanClass(mbd, beanName);
    
                       //  class   ,       public
    
                       if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    
                       }
    
                       //        callback    ,    callback  bean
    
                       Supplier> instanceSupplier = mbd.getInstanceSupplier();
    
                       if (instanceSupplier != null) {
    
                                return obtainFromSupplier(instanceSupplier, beanName);
    
                       }
    
                       //        
    
                       if (mbd.getFactoryMethodName() != null)  {
    
                                return instantiateUsingFactoryMethod(beanName, mbd, args);
    
                       }
    
                      
    
                       //            ,  Spring       、            
    
                       //            ,Spring                         ,        bean     
    
                       boolean resolved = false;
    
                       boolean autowireNecessary = false;
    
                       if (args == null) {
    
                                synchronized (mbd.constructorArgumentLock) {
    
                                         if (mbd.resolvedConstructorOrFactoryMethod != null) {
    
                                                   //     class    
    
                                                   resolved = true;
    
                                                   autowireNecessary = mbd.constructorArgumentsResolved;
    
                                         }
    
                                }
    
                       }
    
                       if (resolved) {
    
                                //     class    ,           
    
                                if (autowireNecessary) {
    
                                         //        
    
                                         return autowireConstructor(beanName, mbd, null, null);
    
                                }
    
                                else {
    
                                         //       
    
                                         return instantiateBean(beanName, mbd);
    
                                }
    
                       }
    
    
    
                       //         、      
    
                       Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    
                       //           ||               || bean          ||        
    
                       if (ctors != null ||
    
                                         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
    
                                         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
    
                                //        
    
                                return autowireConstructor(beanName, mbd, ctors, args);
    
                       }
    
    
    
                       //        
    
                       return instantiateBean(beanName, mbd);
    
             }

    5. Bean 실례 화 후 단계 - populate Bean
    Bean 실례 화 를 완료 하면 Spring 용 기 는 이 Bean 에 관련 된 의존 Bean 과 속성 대 가 를 주입 합 니 다.원본 코드 에서 이 단 계 는 Abstract AutowireCapableBean Factory 의 populateBean 방법 으로 이 루어 집 니 다.원본 코드 분석 은 다음 과 같 습 니 다.
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    
        // pvs   MutablePropertyValues  ,     PropertyValues  ,           ,                 
    
        //     ,      propertyValueList,      propertyValue:key->value="student"->RuntimeBeanReference("")
    
             PropertyValues pvs = mbd.getPropertyValues();
    
    
    
             if (bw == null) {
    
                       if (!pvs.isEmpty()) {
    
                                throw new BeanCreationException(
    
                                                   mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
    
                       }
    
                       else {
    
                                //        
    
                                return;
    
                       }
    
             }
    
    
    
             //  InstantiationAwareBeanPostProcessors              Bean    
    
             //       postProcessAfterInstantiation  ,      false,            ,    
    
             boolean continueWithPropertyPopulation = true;
    
    
    
             if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
                       for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
                                if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
                                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    
                                         if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    
                                                   continueWithPropertyPopulation = false;
    
                                                   break;
    
                                         }
    
                                }
    
                       }
    
             }
    
    
    
             if (!continueWithPropertyPopulation) {
    
                       return;
    
             }
    
    
    
        //   Bean             ,   0,       ,           xml         
    
        //               ,   Bean    ,              ,      
    
             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
    
                                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    
                       //           
    
                       MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    
    
    
                       //         
    
                       if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
    
                                autowireByName(beanName, mbd, bw, newPvs);
    
                       }
    
    
    
                       // //         
    
                       if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    
                                autowireByType(beanName, mbd, bw, newPvs);
    
                       }
    
            //         ,      
    
                       pvs = newPvs;
    
             }
    
       
    
        //        InstantiationAwareBeanPostProcessor
    
             boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    
             //         
    
             boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
       
    
             if (hasInstAwareBpps || needsDepCheck) {
    
                 //                    
    
                       PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    
                       if (hasInstAwareBpps) {
    
                                for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
                                    //            ,      
    
                                         if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
                                                   InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    
                                                   pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    
                                                   if (pvs == null) {
    
                                                            return;
    
                                                   }
    
                                         }
    
                                }
    
                       }
    
                       if (needsDepCheck) {
    
                           //             ,   depends-on  ,         Bean      
    
                                checkDependencies(beanName, mbd, filteredPds, pvs);
    
                       }
    
             }
    
        //  pvs         BeanWrapper   Bean   ,      ,TestBean student    RuntimeBeanReference,        Student  
    
             applyPropertyValues(beanName, mbd, bw, pvs);
    
    }

     
    6. Bean 초기 화 단계 - initializeBean
    BeanFactory 가 bean 을 성공 적 으로 만 들 고 모든 속성 을 설정 한 후에 초기 화 를 해 야 합 니 다. initializeBean 방법 으로 초기 화 를 해 야 합 니 다. 소스 코드 는 다음 과 같 습 니 다.        
    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    
                       if (System.getSecurityManager() != null) {
    
                                AccessController.doPrivileged((PrivilegedAction) () -> {
    
                                         invokeAwareMethods(beanName, bean);
    
                                         return null;
    
                                }, getAccessControlContext());
    
                       }
    
                       else {
    
                                invokeAwareMethods(beanName, bean);
    
                       }
    
    
    
                       Object wrappedBean = bean;
    
                       if (mbd == null || !mbd.isSynthetic()) {
    
                                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    
                       }
    
    
    
                       try {
    
                                invokeInitMethods(beanName, wrappedBean, mbd);
    
                       }
    
                       catch (Throwable ex) {
    
                                throw new BeanCreationException(
    
                                                   (mbd != null ? mbd.getResourceDescription() : null),
    
                                                   beanName, "Invocation of init method failed", ex);
    
                       }
    
                       if (mbd == null || !mbd.isSynthetic()) {
    
                                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    
                       }
    
    
    
                       return wrappedBean;
    
             }

    전체 초기 화 프로 세 스 는 다음 과 같 습 니 다.
    1. 각종 감지 Aware 인터페이스 호출
    2. applyBeanPostProcessors BeforeInitialization 초기 화 전 처리 작업 수행
    3. InitialingBean 인터페이스 초기 화 호출
    4. method - init 가 설정 되 어 있 으 면 그 방법 으로 초기 화 합 니 다.
    5. applyBeanPostProcessors After Initialization 초기 화 후 처리 작업 호출
     
    7. Bean 소각 단계 - destroyBean
    1. 이 단일 bean 에 의존 하 는 모든 bean 을 먼저 없 애 는 것 은 매우 간단 합 니 다. 만약 에 현재 단일 bean 이 소각 되면 현재 단일 bean 에 의존 하 는 bean 대상 이 단일 bean 을 호출 할 때 반드시 빈 포인터 이상 이 발생 합 니 다.
    2. 본 격 적 으로 단일 bean 의 destroy () 방법 을 실행 하여 bean 을 소각 합 니 다.
    3. contained BeanMap 은 이 단일 bean 에 포 함 된 다른 bean 대상 (즉, 도입 의존) 을 소각 합 니 다. 그러나 실제 이 map 는 사용 되 지 않 은 것 같 습 니 다. 또한 인용 한 bean 도 즉시 소각 해 서 는 안 됩 니 다. 다른 bean 이 동시에 인용 되 고 있 을 수 있 기 때문에 인용 되 지 않 았 을 때 소각 해 야 할 지도 모 르 지만 spring 에 서 는 그렇지 않 은 것 같 습 니 다)
    4. bean 캐 시 목록 dependentBeanMap 에서 (예 를 들 어 service - > controller list) 관련 의존 항목 을 모두 삭제 합 니 다.
    5. 의존 목록 dependenciesForBeanMap 삭제 (키 쌍, 예 를 들 어 controller - > service list)
    원본 코드 는 다음 과 같 습 니 다.
    protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
    
                       // Trigger destruction of dependent beans first...
    
                       Set dependencies;
    
                       synchronized (this.dependentBeanMap) {
    
                                // Within full synchronization in order to guarantee a disconnected Set
    
                                dependencies = this.dependentBeanMap.remove(beanName);
    
                       }
    
                       if (dependencies != null) {
    
                                if (logger.isTraceEnabled()) {
    
                                         logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
    
                                }
    
                                for (String dependentBeanName : dependencies) {
    
                                         destroySingleton(dependentBeanName);
    
                                }
    
                       }
    
    
    
                       // Actually destroy the bean now...
    
                       if (bean != null) {
    
                                try {
    
                                         bean.destroy();
    
                                }
    
                                catch (Throwable ex) {
    
                                         if (logger.isWarnEnabled()) {
    
                                                   logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
    
                                         }
    
                                }
    
                       }
    
    
    
                       // Trigger destruction of contained beans...
    
                       Set containedBeans;
    
                       synchronized (this.containedBeanMap) {
    
                                // Within full synchronization in order to guarantee a disconnected Set
    
                                containedBeans = this.containedBeanMap.remove(beanName);
    
                       }
    
                       if (containedBeans != null) {
    
                                for (String containedBeanName : containedBeans) {
    
                                         destroySingleton(containedBeanName);
    
                                }
    
                       }
    
    
    
                       // Remove destroyed bean from other beans' dependencies.
    
                       synchronized (this.dependentBeanMap) {
    
                                for (Iterator>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
    
                                         Map.Entry> entry = it.next();
    
                                         Set dependenciesToClean = entry.getValue();
    
                                         dependenciesToClean.remove(beanName);
    
                                         if (dependenciesToClean.isEmpty()) {
    
                                                   it.remove();
    
                                         }
    
                                }
    
                       }
    
    
    
                       // Remove destroyed bean's prepared dependency information.
    
                       this.dependenciesForBeanMap.remove(beanName);
    
             }

    좋은 웹페이지 즐겨찾기