今天小编给大家分享一下Spring refresh()源码分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
正文
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(); } } }
一、prepareRefresh:初始化前的预处理
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(); }
1.1初始化属性值
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)); } }
1.2属性校验
通过占位符解析器校验资源集合
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
二、obtainFreshbeanfactory:刷新Bean工厂
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()); }
三、preparebeanfactory:Bean工厂预处理
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()); } }
3.1 ApplicationContextDProcessor:Aware执行器
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); } }
3.2 registerResolvableDependency:自动注入的支持
如果过容器中有多个相同接口的实现类,那么在自动注入的时候会注入注册的实现类
beanfactory.registerResolvableDependency(beanfactory.class, beanfactory); beanfactory.registerResolvableDependency(ResourceLoader.class, this); beanfactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanfactory.registerResolvableDependency(ApplicationContext.class, this);
3.3 添加监听器执行器
ApplicationListenerDetector主要作用是添加和销毁监听器,实现了BeanPostProcessor的postProcessAfterInitialization(Bean实例化之后)方法和DestructionAwareBeanPostProcessor的postProcessBeforeDestruction(Bean销毁之前)方法
四、beanfactory的后置处理
这是个模压方法,由子类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)); } }
4.1 后置处理bean工厂
父类ServletWebServerApplicationContext首先向Bean工厂中注入了一个执行器
protected void postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) { //4.1.1注入执行器 beanfactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); beanfactory.ignoreDependencyInterface(ServletContextAware.class); //4.1.2注册作用域 registerWebApplicationScopes(); }
4.1.1 WebApplicationContextServletContextAwareProcessor
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; }
4.1.2 registerWebApplicationScopes 注册web的应用域
// 所在类及方法: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()源码分析”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程之家行业资讯频道。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。