Spring 소스 코드 (4) Context 편의 AbstractApplication Context (상)
50947 단어 spring
새로 고침 방법 이 어떤 일 을 했 는 지 살 펴 보 자.
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
그 첫 번 째 집행
prepareRefresh()
방법 은 말 그대로 리 셋 을 위 한 준비 입 니 다!/**
1. Prepare this context for refreshing, setting its startup date and
2. active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
this.startupDate = System.currentTimeMillis();
context 의 시작 시간 을 설정 합 니 다.this.closed.set(false);
context 의 닫 기 표 지 를 false 로 설정 합 니 다.this.active.set(true);
context 의 활동 표 지 를 true 로 설정 합 니 다.initPropertySources();
context environment (컨 텍스트 환경) 의 자리 차지 문자 속성 원본 을 초기 화 합 니 다.getEnvironment().validateRequiredProperties();
'필수' 로 표 시 된 모든 속성 을 분석 할 수 있 는 지 검증 this.earlyApplicationEvents = new LinkedHashSet();
spring event 발표 및 감청 사례 prepareRefresh()
방법, 콘 솔 은 다음 로 그 를 인쇄 합 니 다.[2019-01-03 16:49:48 INFO org.springframework.web.context.support.XmlWebApplicationContext:583] Refreshing Root WebApplicationContext: startup date [Thu Jan 03 16:49:40 CST 2019]; root of context hierarchy
두 번 째 실행
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
은 AbstractApplication Context 의 하위 클래스 를 내부 bean 공장 으로 갱신 합 니 다 (사실은 bean 공장 을 다시 만 드 는 것 입 니 다).protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
그 중에서
refreshBeanFactory()
방법 은 Abstract Refreshable Application Context 류 의 refreshBean Factory () 방법 을 호출 했 습 니 다. 지난 편의 클래스 관계 도 에서 우 리 는 Abstract Refreshable Application Context 류 가 Abstract Application Context 류 의 하위 클래스 라 는 것 을 알 고 있 습 니 다.AbstractRefreshable Application Context 의
refreshBeanFactory()
방법:@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
이 방법의 논 리 는 위 에서 아래로 새로운 BeanFactory 를 초기 화하 고 정 의 된 Bean 에서 BeanFactory 까지 불 러 오 는 것 입 니 다.
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
Bean 을 BeanFactory 에 불 러 오 려 면 xml 를 옮 겨 다 니 며 해석 합 니 다. 어떤 xml 을 해석 합 니까?
코드 를 따라 가면 loadBeanDefinitions 방법 이 XmlWebApplication Context 류 의 loadBeanDefinitions 방법 을 호출 하 는 것 을 방금 발견 할 수 있 습 니 다.
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
그 중에서 재 추적
loadBeanDefinitions()
방법 소스 코드:protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
여기
getConfigLocations()
방법 은 부모 클래스 Abstract Refreshable ConfigApplication Context 의 configLocations 변 수 를 가 져 왔 습 니 다. 지난 편 에 서 는 contextConfigLocation 의 설정 (웹. xml 에서 설정) 을 말 했 고 설정 한 value 값 이 Abstract Refreshable ConfigApplication Context 류 의 configLocations 변수 에 설정 되 었 다 고 말 했 습 니 다. 이것 이 맞 잖 아 요!!<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/*.xml
프로젝트 에 불 러 올 xml 파일 의 위 치 를 설정 합 니 다. 이 xml 파일 들 은 위
loadBeanDefinitions
방법의 for 순환 을 통 해 일일이 불 러 오기 분석 을 하고 Bean 을 초기 화 하 며 Bean 인 스 턴 스 를 BeanFactory 에 두 었 습 니 다. BeanFactory 는 마지막 으로 Context 관리 에 맡 깁 니 다!실행
loadBeanDefinitions(XmlBeanDefinitionReader reader)
방법 은 다음 로 그 를 입력 합 니 다 (로그 분석 원 과 결합 하여 더 잘 알 수 있 습 니 다).[2019-01-09 15:10:52 INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:317] Loading XML bean definitions from file [D:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\wtpwebapps\accplatform-job\WEB-INF\classes\spring\applicationContext-msg.xml]
[2019-01-09 15:10:57 INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:317] Loading XML bean definitions from file [D:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\wtpwebapps\accplatform-job\WEB-INF\classes\spring\applicationContext-redis.xml]
[2019-01-09 15:10:57 INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:317] Loading XML bean definitions from file [D:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\wtpwebapps\accplatform-job\WEB-INF\classes\spring\applicationContext.xml]
세 번 째 refresh () 에서
prepareBeanFactory(beanFactory);
방법 을 실행 합 니 다. 아래 Spring 컨 텍스트 에서 BeanFactory 를 사용 하여 준비 하기 위해 소스 코드 를 확인 합 니 다.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());
}
}
소스 코드 를 통 해 알 수 있 듯 이 이 방법 은 기본적으로 BeanFactory 의 데 이 터 를 초기 화 하 는 것 입 니 다. BeanFactory 의 배치 화 (Configure) 과정 이 라 고도 부 릅 니 다. BeanFctory 는 Spring IOC 의 중점 류 (약간 복잡 합 니 다) 에 속 합 니 다. 그 다음 에 Spring IOC 의 측면 에서 Spring 의 Bean 공장 시 리 즈 를 전면적으로 해석 해 야 합 니 다. 지금 은 Spring Context 의 측면 에서 해석 하기 때문에 간단하게 가 져 가 야 합 니 다.
그 네 번 째 refresh () 에서 실행
postProcessBeanFactory(beanFactory);
은 사실 Abstract Refreshable Webapplication Context 류 의 방법 을 실 행 했 습 니 다.@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
여기 서 중요 한 것 은 다음 두 줄 의 코드 입 니 다. 웹 의 특정한 역할 영역 ("request", "session", "globalSession", "application") 부터 BeanFactory 까지 웹 응용 프로그램 Context 를 편리 하 게 사용 할 수 있 습 니 다. 역할 영역 은 여기 서 먼저 이렇게 이해 할 수 있 습 니 다 (Bean 의 생 성 측면 에서 이해).
invokeBeanFactoryPostProcessors(beanFactory);
의 소스 코드 는 다음 과 같다./**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
소스 코드 주석 을 통 해 알 수 있 듯 이 이 방법의 호출 은 모든 singleton 이 예화 되 기 전에 이 방법의 이름 을 통 해 알 수 있 듯 이 IOC 의 Processor 역할 (사실은 Bean 공장 의 프로세서) 을 도입 했다. Bean 의 프로세서 아래 에서 대량의 복잡 한 작업 을 했 고 구체 적 으로 어떤 작업 을 했 는 지 알 수 있다. Context 편 시스템 은 여기 서 깊이 분석 하지 않 는 다.
그 6 refresh () 에서 실행
registerBeanPostProcessors(beanFactory);
의 원본 코드 는 다음 과 같다./**
* Instantiate and invoke all registered BeanPostProcessor beans,
* respecting explicit order if given.
* Must be called before any instantiation of application beans.
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
아니면 빈 팩 토리 에 대한 처리!!refresh () 방법 은 두 번 째 부터 여섯 번 째 까지 모두 BeanFactory 에 관 한 처리 입 니 다.
다음은 AbstractApplication Context 의
refresh()
를 해석 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.