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 을 되 돌려 줍 니 다.
그 중에서 우 리 는 그 중의 몇 가지 부분 을 주의해 야 한다.
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
전체 초기 화 프로 세 스 는 다음 과 같 습 니 다.
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);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.