이 절 에 서 는 Application Context 와 Bean 의 초기 화 와 소각 을 배 웁 니 다. 우선 애플 리 케 이 션 Context 용기 의 초기 화 와 소각 닫 기 과정 을 살 펴 보 자. 응용 프로그램 Context 가 시작 되 는 과정 은 Abstract 응용 프로그램 Context 에서 이 루어 집 니 다.응용 컨 텍스트 를 사용 할 때 준비 작업 이 필요 합 니 다. 이 준비 작업 은 prepareBeanFactory 방법 에서 이 루어 집 니 다.이 방법 은 용기 에 ClassLoader, Property Editor, BeanPostProcessor 등 을 설정 합 니 다.
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
용 기 를 닫 을 때 도 시스템 작업 을 완료 해 야 합 니 다. 이 작업 은 doClose () 방법 에서 이 루어 집 니 다. 이 방법 에서 먼저 용기 가 닫 힌 다 는 신 호 를 보 낸 다음 빈 을 하나씩 닫 고 마지막 으로 용기 자 체 를 닫 습 니 다.
protected void doClose() {
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isInfoEnabled()) {
logger.info("Closing " + this);
}
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// Close the state of this context itself.
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
this.active.set(false);
}
}
용기 구현 은 빈 의 라 이 프 사이클 을 IOC 관리 로 이 뤄 진다.Spring IOC 용 기 는 Bean 수명 주 기 를 관리 할 때 Bean 수명 주기 각 시간 대의 리 셋 을 제공 합 니 다. IOC 용기 에서 Bean 의 라 이 프 사이클 을 간단히 소개 해 드 리 겠 습 니 다.
Bean 인 스 턴 스 생 성
Bean 의 인 스 턴 스 설정 속성
Bean 초기 화 방법 호출
응용 은 IOC 용 기 를 통 해 Bean
을 사용 할 수 있다.
용기 가 꺼 졌 을 때 Bean 의 소각 방법
을 호출 합 니 다. Bean 의 초기 화 방법 은 Abstract AutowireCapableBean Factory 의 initializeBean 방법 에서 이 루어 집 니 다.
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
Bean 의 초기 화 방법 을 호출 하기 전에 일련의 aware 인 터 페 이 스 를 호출 하여 관련 BeanName, BeanClassLoader, BeanFactory 를 Bean 에 주입 합 니 다. 이 어 빈 의 사후 처 리 를 통 해 애플 리 케 이 션 빈 포스트 프로 세 서 스 Before Initialization 방법 을 볼 수 있 습 니 다. BeanPostProcessor 는 Bean 의 백 엔 드 프로세서 로 용기 가 촉발 하 는 사건 을 감청 할 수 있 는 모니터 입 니 다.이 를 IOC 용기 에 등록 하면 용기 에서 관리 하 는 빈 은 IOC 용기 이 벤트 를 리 셋 받 는 능력 을 갖 췄 다. 이 BeanPost Processor 는 하나의 인터페이스 로 두 개의 인터페이스 방법 이 있 습 니 다. 하 나 는 post Process Before Initialization 입 니 다. Bean 의 초기 화 전에 리 셋 입 구 를 제공 합 니 다.하 나 는 post Process After Initialization 으로 Bean 의 초기 화 후 리 셋 입 구 를 제공 합 니 다. 이 두 리 셋 의 트리거 는 모두 용기 관리 Bean 의 수명 주기 와 관련 이 있 습 니 다.두 방법의 매개 변 수 는 같은 것 으로 각각 Bean 의 실례 화 대상 과 bean 의 이름 이다.
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
빈 포스트 프로세서 의 post Process Before Initialization 방법 을 순서대로 호출 합 니 다. 이 어 invoke InitMethods 호출 을 볼 수 있 습 니 다. 이 때 는 after PropertiesSet 을 시작 하 는 과정 도 볼 수 있 습 니 다. 물론 이 는 Bean 이 InitialingBean 의 인 터 페 이 스 를 실현 해 야 합 니 다. 해당 하 는 초기 화 처 리 는 after PropertiesSet 방법 에서 이 루어 질 수 있 습 니 다.
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction
마지막 으로 빈 이 initMethod 를 설정 하 는 지 여 부 를 판단 합 니 다. 있 으 면 invoke CustomInitMethod 방법 으로 호출 하여 빈 의 초기 화 를 완료 합 니 다.
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
if (logger.isDebugEnabled()) {
logger.debug("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isDebugEnabled()) {
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
마지막 호출 후 프로세서 applyBeanPostProcessors AfterInitialization
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
후 처리 장 치 는 빈 포스트 프로세서 의 post Process After Initialization 방법 을 순서대로 호출 합 니 다. 다음은 Bean 의 소각 과정 을 살 펴 보 겠 습 니 다. AbstractApplication Context 류 의 doClose 방법 을 보십시오.
protected void doClose() {
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isInfoEnabled()) {
logger.info("Closing " + this);
}
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// Close the state of this context itself.
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
this.active.set(false);
}
}
destroy Beans 방법, Bean 소각 처리.결국 Disposable Bean Adapter 의 destroy 방법 으로 이 루어 졌 습 니 다.
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction) () -> {
((DisposableBean) bean).destroy();
return null;
}, acc);
}
else {
((DisposableBean) bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
여기 서 Bean 에 대한 소각 과정 을 볼 수 있 습 니 다. 먼저 post Process BeforeDestruction 을 호출 한 다음 에 Bean 의 destroy 방법 을 호출 합 니 다. DisposableBean 인 터 페 이 스 를 실현 하고 마지막 으로 Bean 의 사용자 정의 소각 방법 을 호출 해 야 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다: