<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { // 1. 初始化前的預處理 this.prepareRefresh(); // 2. 重新整理Bean工廠 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 3. BeanFactory的預處理設定 this.prepareBeanFactory(beanFactory); try { // 4. BeanFactory的後置處理 this.postProcessBeanFactory(beanFactory); // 5. 執行BeanFactory後置處理器 this.invokeBeanFactoryPostProcessors(beanFactory); // 6. 註冊Bean的後置處理器 this.registerBeanPostProcessors(beanFactory); // 7. 初始化MessageSource this.initMessageSource(); // 8. 初始化事件派發器 this.initApplicationEventMulticaster(); // 9. 子類的多型onRefresh this.onRefresh(); // 10. 註冊監聽器 this.registerListeners(); // 11. 初始化所有剩下的單例Bean this.finishBeanFactoryInitialization(beanFactory); // 12. 完成容器的建立工作 this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { // 13. 清除快取 this.resetCommonCaches(); } } }
protected void prepareRefresh() { //設定容器啟動時間 this.startupDate = System.currentTimeMillis(); //設定容器關閉狀態為false this.closed.set(false); //設定容器啟用狀態為true this.active.set(true); if (this.logger.isDebugEnabled()) { if (this.logger.isTraceEnabled()) { this.logger.trace("Refreshing " + this); } else { this.logger.debug("Refreshing " + this.getDisplayName()); } } //1.1初始化屬性資源 this.initPropertySources(); //1.2校驗 this.getEnvironment().validateRequiredProperties(); this.earlyApplicationEvents = new LinkedHashSet(); }
初始化方法是個模壓方法,由子類重寫
protected void initPropertySources() { }
Web容器GenericWebApplicationContext重寫了此方法
protected void initPropertySources() { //獲取環境資訊 ConfigurableEnvironment env = getEnvironment(); //判斷是否是web設定環境 if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null); } }
最終由StandardServletEnvironment進行初始化
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { //使用web容器工具初始化 WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig); }
把 Servlet 的一些初始化引數放入IOC容器中
public static void initServletPropertySources(MutablePropertySources sources, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { Assert.notNull(sources, "'propertySources' must not be null"); String name = "servletContextInitParams"; if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) { sources.replace(name, new ServletContextPropertySource(name, servletContext)); } name = "servletConfigInitParams"; if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) { sources.replace(name, new ServletConfigPropertySource(name, servletConfig)); } }
通過預留位置解析器校驗資源集合
public void validateRequiredProperties() throws MissingRequiredPropertiesException { this.propertyResolver.validateRequiredProperties(); }
這裡的解析器作為常數在環境被範例化時就被建立出來的,PropertySourcesPropertyResolver是預留位置解析器,將資料來源中預留位置替換成目標值
校驗是否有需要被預留位置修飾的屬性,如果有但是資源中找不到對應屬性的key就會丟擲異常
public void validateRequiredProperties() { MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException(); for (String key : this.requiredProperties) { if (this.getProperty(key) == null) { ex.addMissingRequiredProperty(key); } } if (!ex.getMissingRequiredProperties().isEmpty()) { throw ex; } }
案例: 資原始檔
name=zhansan age=${name},10 encoding=utf-8 name2=${name}
測試程式碼
@Test public void test1() throws Exception { //省略propertySources PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(getPropertySources()); System.out.println(propertyResolver.getProperty("age")); System.out.println(propertyResolver.getProperty("encoding")); System.out.println(propertyResolver.resolvePlaceholders("must be encoding ${encoding}")); //輸出must be encoding gbk }
輸出結果
10,zhansan
utf-8
must be encoding utf-8
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //2.1重新整理Bean工廠 refreshBeanFactory(); return getBeanFactory(); }
將容器重新整理標識改為true,並且設定了工廠序列化id
protected final void refreshBeanFactory() throws IllegalStateException { if (!this.refreshed.compareAndSet(false, true)) { throw new IllegalStateException( "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once"); } this.beanFactory.setSerializationId(getId()); }
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 設定BeanFactory的類載入器、表示式解析器等 beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 3.1 新增Aware執行器 beanFactory.addBeanPostProcessor(new ApplicationContextDProcessor(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); // 3.2 自動注入的支援 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // 3.3 新增監聽器執行器 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()); } }
ApplicationContextDProcessor實現了BeanPostProcessor的postProcessBeforeInitialization介面,在所有Bean初始化前會執行當前方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { //判斷Bean是Aware的子類 if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){ return bean; } AccessControlContext acc = null; if (System.getSecurityManager() != null) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { //回撥執行Aware介面 invokeAwareInterfaces(bean); } return bean; }
如果當前Bean是Aware的子類,那麼將Bean強轉成Aware型別,通過回撥將資訊設定到Bean中
private void invokeAwareInterfaces(Object bean) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } }
如果過容器中有多個相同介面的實現類,那麼在自動注入的時候會注入註冊的實現類
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this);
ApplicationListenerDetector主要作用是新增和銷燬監聽器,實現了BeanPostProcessor的postProcessAfterInitialization(Bean範例化之後)方法和DestructionAwareBeanPostProcessor的postProcessBeforeDestruction(Bean銷燬之前)方法
詳情:https://www.jb51.net/article/277948.htm
這是個模壓方法,由子類AnnotationConfigServletWebServerApplicationContext實現
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }
AnnotationConfigServletWebServerApplicationContext首先調了父類別 ServletWebServerApplicationContext 的 postProcessBeanFactory 方法
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { //4.1後置處理Bean工廠 super.postProcessBeanFactory(beanFactory); if (this.basePackages != null && this.basePackages.length > 0) { //basePackages為空不會執行 this.scanner.scan(this.basePackages); } if (!this.annotatedClasses.isEmpty()) { this.reader.register(ClassUtils.toClassArray(this.annotatedClasses)); } }
父類別ServletWebServerApplicationContext首先向Bean工廠中注入了一個執行器
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { //4.1.1注入執行器 beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); //4.1.2註冊作用域 registerWebApplicationScopes(); }
WebApplicationContextServletContextAwareProcessor繼承了ServletContextAwareProcessor
ServletContextAwareProcessor繼承了BeanPostProcessor實現了postProcessBeforeInitialization(Bean初始化前執行)
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { //注入ServletContext if (getServletContext() != null && bean instanceof ServletContextAware) { ((ServletContextAware) bean).setServletContext(getServletContext()); } //注入ServletConfig if (getServletConfig() != null && bean instanceof ServletConfigAware) { ((ServletConfigAware) bean).setServletConfig(getServletConfig()); } return bean; }
// 所在類及方法:ServletWebServerApplicationContext#registerWebApplicationScopes private void registerWebApplicationScopes() { ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory()); WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory()); existingScopes.restore(); }
ExistingWebApplicationScopes是ServletWebServerApplicationContext類中的一個靜態類
原始碼如下:
public static class ExistingWebApplicationScopes { static { Set<String> scopes = new LinkedHashSet<>(); scopes.add(WebApplicationContext.SCOPE_REQUEST); scopes.add(WebApplicationContext.SCOPE_SESSION); SCOPES = Collections.unmodifiableSet(scopes); } // 這是構造方法,大概就是根據SCOPES獲取beanFactory中已經註冊的scope,然後放入scopes // 需要注意的是,在上面的方法中,第二行才在向beanFactory中註冊,也就是這時的beanFactory裡面沒有request和session這兩個scop // 所以這裡就完成了beanFactory的賦值。建議打斷點進去看看 public ExistingWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) { this.beanFactory = beanFactory; for (String scopeName : SCOPES) { Scope scope = beanFactory.getRegisteredScope(scopeName); if (scope != null) { this.scopes.put(scopeName, scope); } } } // 由於上面的方法並沒有值存入scopes,所以這裡也就沒執行裡面的內容 public void restore() { this.scopes.forEach((key, value) -> { if (logger.isInfoEnabled()) { logger.info("Restoring user defined scope " + key); } this.beanFactory.registerScope(key, value); }); } }
WebApplicationContextUtils.registerWebApplicationScopes(),這個方法就是向beanFactory註冊web的scope了,原始碼如下
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) { registerWebApplicationScopes(beanFactory, null); } public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, @Nullable ServletContext sc) { // 註冊作用域 beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());// 註冊request SCOP beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());// 註冊session SCOP if (sc != null) { ServletContextScope appScope = new ServletContextScope(sc); beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope); // 註冊application SCOP // Register as ServletContext attribute, for ContextCleanupListener to detect it. sc.setAttribute(ServletContextScope.class.getName(), appScope); } // 新增依賴項 beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory()); beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory()); beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory()); beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory()); if (jsfPresent) { FacesDependencyRegistrar.registerFacesDependencies(beanFactory); } }
以上就是Spring refresh()原始碼解析的詳細內容,更多關於Spring refresh()的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45