最好的技术,就是让你感受不到技术的存在java
【小家Spring】Spring IOC容器启动流程 AbstractApplicationContext#refresh()方法源码分析(一)
【小家Spring】Spring IOC容器启动流程 AbstractApplicationContext#refresh()方法源码分析(二)
【小家Spring】AbstractBeanFactory#getBean()、doGetBean完成Bean的初始化、实例化,以及BeanPostProcessor后置处理器源码级详细分析
【小家Spring】AbstractAutowireCapableBeanFactory#populateBean实现Bean的依赖注入(属性赋值)和initializeBean对Bean的初始化
【小家Spring】Spring解析@Configuration注解的处理器:ConfigurationClassPostProcessor(ConfigurationClassParser)web
【小家Spring】细说Spring IOC容器的自动装配(@Autowired),以及Spring4.0新特性之【泛型依赖注入】的源码级解析spring
还记得我在这篇博文:【小家Spring】Spring容器(含父子容器)的启动过程源码级别分析(含web.xml启动以及全注解驱动,和ContextLoader源码分析)
里留了几个很是重要,可是没有解释的方法。其中有一个很是重要的方法ApplicationContext#refresh()
方法就是提到两次但都暂时忽略了(由于有父子容器,因此会刷新两次容器~)编程
refresh()
方法是Spring容器启动的核心中的核心,逻辑也是异常的复杂,由于准备分两篇文章来叙述他的过程,以及源码的分析缓存
Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)
Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)
Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)安全
Spring Bean的完整生命周期从建立Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点。
我把这张图放在最开始的位置,初看可能以为一脸懵逼,可是相信在接下来的阅读过程当中,会一步一步的柳暗花明的~
简单分类以下:微信
BeanFactoryPostProcessor
):这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer
等等很是有用的工厂后处理器 接口的方法。工厂后处理器也是容器级的。InstantiationAwareBeanPostProcessor 和 BeanPostProcessor
这两个接口实现,通常称它们的实现类为“后处理器”BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean
这些接口的方法<bean>
的init-method
和destroy-method
指定的方法由于咱们项目的案例是全注解驱动的,所以咱们的容器实例为:AnnotationConfigWebApplicationContext
(若你是xml配置驱动,则为XmlWebApplicationContext
)session
为了更方便了解容器类的继承关系,贴出以下类继承图:
app
refresh()
方法全部的ApplicationContext
子类都没重写,只有AbstractApplicationContext
里有实现过(接口定义在ConfigurableApplicationContext
),所以咱们看起来也容易了,直接上源码~框架
此部分源码,把容器的刷新步骤体现得很是的清晰,十足的面向对象编程。所以我会保留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. // 获取新的beanFactory,销毁原有beanFactory、为每一个bean生成BeanDefinition等 注意,此处是获取新的,销毁旧的,这就是刷新的意义 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //配置标准的beanFactory,设置ClassLoader,设置SpEL表达式解析器等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //模板方法,容许在子类中对beanFactory进行后置处理。 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //实例化并调用全部注册的beanFactory后置处理器(实现接口BeanFactoryPostProcessor的bean)。 //在beanFactory标准初始化以后执行 例如:PropertyPlaceholderConfigurer(处理占位符) invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //实例化和注册beanFactory中扩展了BeanPostProcessor的bean。 //例如: //AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入) //RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法) //CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的做用)等。 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //初始化国际化工具类MessageSource initMessageSource(); // Initialize event multicaster for this context. //初始化事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //模板方法,在容器刷新的时候能够自定义逻辑(子类本身去实现逻辑),不一样的Spring容器作不一样的事情 onRefresh(); // Check for listener beans and register them. //注册监听器,而且广播early application events,也就是早期的事件 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //很是重要。。。实例化全部剩余的(非懒加载)单例Bean。(也就是咱们本身定义的那些Bean们) //好比invokeBeanFactoryPostProcessors方法中根据各类注解解析出来的类,在这个时候都会被初始化 扫描的 @Bean之类的 //实例化的过程各类BeanPostProcessor开始起做用~~~~~~~~~~~~~~ finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //refresh作完以后须要作的其余事情 //清除上下文资源缓存(如扫描中的ASM元数据) //初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。 //发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操做 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. //若是刷新失败那么就会将已经建立好的单例Bean销毁掉 destroyBeans(); // Reset 'active' flag. //重置context的活动状态 告知是失败的 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... // 失败与否,都会重置Spring内核的缓存。由于可能再也不须要metadata给单例Bean了。 resetCommonCaches(); } } }
经过上面的注释,已经可以比较宏观的了解到容器的一个初始化过程了,那么接下来,将针对每个步骤,进行微观源码级别的解释说明。
protected void prepareRefresh() { //记录容器启动时间,而后设立对应的标志位 this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); // 打印info日志:开始刷新this此容器了 if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } // Initialize any placeholder property sources in the context environment // 这是扩展方法,由子类去实现,能够在验证以前为系统属性设置一些值能够在子类中实现此方法 // 由于咱们这边是AnnotationConfigApplicationContext,能够看到无论父类仍是本身,都什么都没作,因此此处先忽略 initPropertySources(); // Validate that all properties marked as required are resolvable // see ConfigurablePropertyResolver#setRequiredProperties //这里有两步,getEnvironment(),而后是是验证是否系统环境中有RequiredProperties参数值 以下详情 // 而后管理Environment#validateRequiredProperties 后面在讲到环境的时候再专门讲解吧 // 这里其实就干了一件事,验证是否存在须要的属性 getEnvironment().validateRequiredProperties(); // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... // 初始化容器,用于装载早期的一些事件 this.earlyApplicationEvents = new LinkedHashSet<>(); }
AbstractApplicationContext#getEnvironment()
关于getEnvironment()
的顶层接口位于:EnvironmentCapable
,有以下实现(注意ConfigurableApplicationContext
是接口,因此其实上容器的实现只有AbstractApplicationContext
):
Demo代码以下:
@Autowired private BeanFactory beanFactory; @Autowired private ApplicationContext applicationContext; @Autowired private ApplicationEventPublisher applicationEventPublisher; //web环境下 @Autowired private HttpServletRequest request; @Autowired private HttpServletResponse response; @Autowired private HttpSession session; @Autowired private WebRequest webRequest; @Override public Object hello() { System.out.println(beanFactory); //org.springframework.beans.factory.support.DefaultListableBeanFactory@3ff27f35 System.out.println(applicationContext); //Root WebApplicationContext: startup date [T ... System.out.println(applicationEventPublisher); //Root WebApplicationContext: startup date [T ... // 咱们发现的是同一个Bean System.out.println(System.identityHashCode(applicationEventPublisher) == System.identityHashCode(applicationContext)); //true //web环境 // =================必须说明一点:这里注入的全部web对象,都是线程安全的================= // 请求N次,每次输出的HashCode都是同样的,那怎么尚未线程安全问题呢?具体看下面分解缘由 System.out.println(System.identityHashCode(request)); System.out.println(request.getClass()); //class com.sun.proxy.$Proxy22 这是个代理对象哟~~~~ System.out.println(request); //Current HttpServletRequest System.out.println(response); //Current HttpServletResponse System.out.println(session); //Current HttpSession System.out.println(webRequest); //Current ServletWebRequest return "service hello"; }
现状:我看到不少同事,还有小伙伴们在Controller层想要使用Servlet
源生API好比HttpServletRequest
的时候,让方法入参了去写,当你的Controller方法多了后(这是必然的),会让代码看起来十分的不优雅(重复工做太多)。
缘由:把request放在方法入参里也不无道理。由于咱们常识性的认为:因为Controller
是单例的,因此直接放在全局属性上,理论上确定是有线程安全问题的。
迷惑点:为了证实这一点,而后每次请求都输出System.identityHashCode(request)
,发现HashCode是不变,所以能够肯定的是,注入的request,确定是同一个实例
线程安全的缘由分析解释:
其实从上面一句request.getClass()
或许能看出端倪的,咱们发现注入的是JDK的动态代理对象class com.sun.proxy.$Proxy22
(至于为什么注入的是代理对象,请参考上面博文:细说Spring IOC容器的自动装配
这一篇有详细的分析讲解,代理类的处理器为:ObjectFactoryDelegatingInvocationHandler
),所以咱们主要看看invoke
方法以下:
(图片所示为该处理器的调用地方和基本源码:)
public static Object resolveAutowiringValue(Object autowiringValue, Class<?> requiredType) { // 若是注入到的值为ObjectFactory类型(而且不是requiredType实例),就猪呢比下面的代理吧~~~ if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) { ObjectFactory<?> factory = (ObjectFactory<?>) autowiringValue; //autowiringValue 显示是实现了Serializable 接口的 // 而且requiredType是个接口(HttpServletRequest是接口,继承自ServletRequest) // 因此此处注意了,只能根据接口进行注入才是线程安全的,若是注入实现类,线程就是不安全的(由于没法建立代理了) 可是显然咱们不可能注入实现类的 if (autowiringValue instanceof Serializable && requiredType.isInterface()) { // 建立出来的代理对象,才是最终要被注入进去的值==== autowiringValue = Proxy.newProxyInstance(requiredType.getClassLoader(), new Class<?>[] {requiredType}, new ObjectFactoryDelegatingInvocationHandler(factory)); } else { return factory.getObject(); } } return autowiringValue; }
ObjectFactoryDelegatingInvocationHandler#invoke
:调用request的方法,都被代理到此处
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if (methodName.equals("equals")) { // Only consider equal when proxies are identical. return (proxy == args[0]); } else if (methodName.equals("hashCode")) { // Use hashCode of proxy. return System.identityHashCode(proxy); } else if (methodName.equals("toString")) { return this.objectFactory.toString(); } try { // 核心在这里,每次调用的方法,实际上调用的是objectFactory.getObject()这个对象的对应方法,那么这个对象源码呢? // beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory()); // 能够看出他是一个RequestObjectFactory类型,因此看下面getObject方法 return method.invoke(this.objectFactory.getObject(), args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } //RequestObjectFactory private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable { // 它每次返回的是和当前线程上下文绑定的一个request副本。至于怎么和上下文绑定的,下面贴出参考连接 // 有了这些解释,那确定的这样注入的是线程安全的,不用再担忧了 @Override public ServletRequest getObject() { return currentRequestAttributes().getRequest(); } @Override public String toString() { return "Current HttpServletRequest"; } }
request上下文是如何跟线程上下文绑定的,参考原理:【小家Spring】Spring MVC执行流程 FrameworkServlet、DispatcherServlet源码分析(processRequest、doDispatch)
小伙伴们之后要使用Servlet源生对象,不要只知道从方法入参里注入,看起来很不优雅,很不Spring MVC化,懂了这些原理前因后果后,相信能够放心的、安全的使用了~
从这方面能够看出,咱们不得不佩服Spring的考虑周到。一个优秀的框架,绝对不只仅是实现了某个功能而已,而是能让你用得舒服,用得爽 ,可扩展性很是强等一些附加属性~~~~好比下面的web容器
AbstractRefreshableWebApplicationContext
就会设置一些初始值:
@Override protected void initPropertySources() { ConfigurableEnvironment env = getEnvironment(); // 初始化web环境中的初始值(好比init等,这个后续会说) if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null); } } @Override public ConfigurableEnvironment getEnvironment() { if (this.environment == null) { this.environment = createEnvironment(); } return this.environment; } // 这个方法须要注意一下,默认是StandardEnvironment,可是它是protected方法设计,因此之类能够重写(以下图) protected ConfigurableEnvironment createEnvironment() { return new StandardEnvironment(); } //StandardServletEnvironment.initPropertySources(this.servletContext, null) @Override public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { // 将 servletContext、servletConfig 添加到 propertySources里(ServletConfigPropertySource) //ServletConfigPropertySource做用:reads init parameters from ServletConfig WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig); }
它们都是web环境下的上下文,所以重写的方式也是如出一辙:
//StandardServletEnvironment是web环境上下文里的Enviroment @Override protected ConfigurableEnvironment createEnvironment() { return new StandardServletEnvironment(); }
StaticWebApplicationContext通常用于测试,几乎不使用
实际上就是从新建立一个bean工厂,并销毁原工厂。主要工做是建立DefaultListableBeanFactory实例,解析配置文件,注册Bean的定义信息
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
在spring中,基本上各司其职,每一个类都有每一个类的做用。其中refreshBeanFactory()
是具体的刷新BeanFactory
,负责这个工做作在类AbstractRefreshableApplicationContext#refreshBeanFactory
中,顾名思义这是专门用来刷新的:
@Override protected final void refreshBeanFactory() throws BeansException { // 判断是否已经存在BeanFactory,存在则销毁全部Beans,而且关闭BeanFactory // 避免重复加载BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 建立具体的beanFactory,这里建立的是DefaultListableBeanFactory,最重要的beanFactory spring注册及加载bean就靠它 // createBeanFactory()这个方法,看下面,还有得说的 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 这句比较简单,就是把当前旧容器的一些配置值复制给新容器 // allowBeanDefinitionOverriding属性是指是否允对一个名字相同但definition不一样进行从新注册,默认是true。 // allowCircularReferences属性是指是否容许Bean之间循环引用,默认是true. // 这两个属性值初始值为空:复写此方法便可customizeBeanFactory customizeBeanFactory(beanFactory); // 这个就是最重要的了,加载全部的Bean配置信息,具体以下详细解释 // 它属于模版方法,由子类去实现加载的方式 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
createBeanFactory()
// 建立的时候就是new了一个工厂:DefaultListableBeanFactory 这个时候工厂里面全部东西都是默认值,不少尚未完成初始化属性的设置呢 protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); } // 给设置父的BeanFactory,若存在的话 public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) { this(); setParentBeanFactory(parentBeanFactory); } // 父类空构造器有这么些语句 public AbstractAutowireCapableBeanFactory() { super(); // 这里是重点。忽略自动装配。这里指定的都是接口。什么意思呢? // ignoreDependencyInterface的真正意思是在自动装配时忽略指定接口的实现类中,对外的依赖。(这里面注意:@Autowired和它的关系,实际上是有坑的,后续会专门讲解这个坑) ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); } //找到父的,若存在就返回 若存在父容器就存在父的BeanFactory @Nullable protected BeanFactory getInternalParentBeanFactory() { return (getParent() instanceof ConfigurableApplicationContext) ? ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent(); }
AnnotationConfigWebApplicationContext#loadBeanDefinitions()
方法,加载Bean的定义 (XmlWebApplicationContext
的实现不同,由于它是加载xml配置文件)
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { // 初始化这个脚手架 其实就是直接new出实例。具体作的工做,下面有相关博文连接 AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory); ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory); // 生成Bean的名称的生成器,若是本身没有setBeanNameGenerator(能够自定义),这里目前为null BeanNameGenerator beanNameGenerator = getBeanNameGenerator(); if (beanNameGenerator != null) { reader.setBeanNameGenerator(beanNameGenerator); scanner.setBeanNameGenerator(beanNameGenerator); //若咱们注册了beanName生成器,那么就会注册进容器里面 beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); } //这是给reader和scanner注册scope的解析器 此处为null ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver(); if (scopeMetadataResolver != null) { reader.setScopeMetadataResolver(scopeMetadataResolver); scanner.setScopeMetadataResolver(scopeMetadataResolver); } // 此处注意了:annotatedClasses和basePackages通常是选其一(固然看到此处,他们是能够并存的) //咱们能够本身指定annotatedClasses 配置文件,同时也能够交给下面扫描 if (!this.annotatedClasses.isEmpty()) { // 这里会把全部的配置文件输出=======info日志 请注意观察控制台 if (logger.isInfoEnabled()) { logger.info("Registering annotated classes: [" + StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]"); } // 如果指明的Bean,就交给reader去处理,至于怎么处理,见上篇博文的doRegisterBean去怎么解析每个Config Bean的 reader.register(ClassUtils.toClassArray(this.annotatedClasses)); } // 也能够是包扫描的方式,扫描配置文件的Bean if (!this.basePackages.isEmpty()) { // 输出对应的info日志 if (logger.isInfoEnabled()) { logger.info("Scanning base packages: [" + StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]"); } // 这里重要了,scan方法具体作了什么事,上篇博文也有详细的介绍,请参阅 scanner.scan(StringUtils.toStringArray(this.basePackages)); } // 此处的意思是,也能够以全类名的形式注册。好比能够调用setConfigLocations设置(这在xml配置中使用较多) 能够是全类名,也能够是包路径 String[] configLocations = getConfigLocations(); if (configLocations != null) { for (String configLocation : configLocations) { try { Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader()); reader.register(clazz); } catch (ClassNotFoundException ex) { // 发现不是全类名,那就看成包扫描吧 int count = scanner.scan(configLocation); } } } }
最开始涉及到两个类的初始化,请参考博文:
【小家Spring】Spring容器加载Bean定义信息的两员大将:AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
有了这篇博文解释这两个类先行,理解上面loadBeanDefinitions
就简单太多了。至此,整个ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这个步骤所有结束。
如今BeanFactory
已经建立了,而且Config配置文件的Bean定义已经注册完成了**(备注:其它单例Bean是尚未解析的~~~~)**
显然,下面的步骤大都把BeanFactory传进去了,都是基于此Bean工厂的了~~~
这个方法是配置工厂的标准上下文特征
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 设置beanFactory的classLoader为当前context的classLoader beanFactory.setBeanClassLoader(getClassLoader()); // 设置EL表达式解析器(Bean初始化完成后填充属性时会用到) // spring3增长了表达式语言的支持,默承认以使用#{bean.xxx}的形式来调用相关属性值 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); // 设置属性注册解析器PropertyEditor 这个主要是对bean的属性等设置管理的一个工具 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 将当前的ApplicationContext对象交给ApplicationContextAwareProcessor类来处理,从而在Aware接口实现类中的注入applicationContext等等 // 添加了一个处理aware相关接口的beanPostProcessor扩展,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置处理方法实现aware相关接口的功能 // 相似的还有ResourceLoaderAware、ServletContextAware等等等等 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); // 下面是忽略的自动装配(也就是实现了这些接口的Bean,不要Autowired自动装配了) // 默认只有BeanFactoryAware被忽略,因此其它的须要自行设置 // 由于ApplicationContextAwareProcessor把这5个接口的实现工做作了(具体你可参见源码) 因此这里就直接忽略掉 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的类,就注册beanFactory // 若是是ResourceLoader、ApplicationEventPublisher、ApplicationContext等等就注入当前对象this(applicationContext对象) // 此处registerResolvableDependency()方法注意:它会把他们加入到DefaultListableBeanFactory的resolvableDependencies字段里面缓存这,供后面处理依赖注入的时候使用 DefaultListableBeanFactory#resolveDependency处理依赖关系 // 这也是为何咱们能够经过依赖注入的方式,直接注入这几个对象好比ApplicationContext能够直接依赖注入 // 可是须要注意的是:这些Bean,Spring的IOC容器里实际上是没有的。beanFactory.getBeanDefinitionNames()和beanFactory.getSingletonNames()都是找不到他们的,因此特别须要理解这一点 // 至于容器中没有,可是咱们仍是能够@Autowired直接注入的有哪些,请看下图: beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // 注册这个Bean的后置处理器:在Bean初始化后检查是否实现了ApplicationListener接口 // 是则加入当前的applicationContext的applicationListeners列表 这样后面广播事件也就方便了 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // 检查容器中是否包含名称为loadTimeWeaver的bean,其实是增长Aspectj的支持 // AspectJ采用编译期织入、类加载期织入两种方式进行切面的织入 // 类加载期织入简称为LTW(Load Time Weaving),经过特殊的类加载器来代理JVM默认的类加载器实现 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { // 添加BEAN后置处理器:LoadTimeWeaverAwareProcessor // 在BEAN初始化以前检查BEAN是否实现了LoadTimeWeaverAware接口, // 若是是,则进行加载时织入,即静态代理。 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 注入一些其它信息的bean,好比environment、systemProperties、SystemEnvironment等 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()); } }
说个小细节:@Autowiredh和@Qualifier一块儿是用时,@Qualifier的值需保证容器里必定有,不然启动报错
这部分比较简单,就是设置一些标准的值,解释都放代码里了。
模版方法。由于beanFactory都准备好了,子类能够本身去实现本身的逻辑。
好比一些web的ApplicationContext,就实现了本身的逻辑,作一些本身的web相关的事情。此处咱们就是web环境下,所以会进来AbstractRefreshableWebApplicationContext#postProcessBeanFactory
方法:
@Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { //注册ServletContextAwareProcessor 这样任意Bean均可以很方便的获取到ServletContext了 同时忽略另外两个,由于ServletContextAwareProcessor 都把事情都作了 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); //注册web环境,包括request、session、golableSession、application WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); //注册servletContext、contextParamters、contextAttributes 、servletConfig单例bean WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); }
这里面两个工具方法,具体作了什么,请参考:
【小家Spring】spring-web包里的一些好用的工具介绍,WebUtils,RequestContextUtils,WebApplicationContextUtils等
invokeBeanFactoryPostProcessors执行BeanFactory后置处理器,固然前提是你已经在容器中注册过此处理器了。
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) // 这里就是定制:若是loadTimeWeaver这个Bean存在,那么就会配置上运行时织入的处理器LoadTimeWeaverAwareProcessor if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
这里面咱们必须先看看getBeanFactoryPostProcessors()
这个方法:
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() { return this.beanFactoryPostProcessors; }
这里很是有意思。方法很是简单,但有意思在于:它不是返回Spring容器里面的Processors,而是你本身的注册的(你本身手动set的),也就是说咱们本身手动调用set方法添加进去,就可以执行。并不须要本身配置@Bean或者在xml里配置
那么重点就在于PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
,它的代码可谓很是很是多:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. // 这个doc说明很清楚:无论怎么样,先执行BeanDefinitionRegistryPostProcessors // 须要注意的是BeanDefinitionRegistryPostProcessors 为 BeanFactoryPostProcessor 的子接口 它新增了方法:void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) // BeanFactoryPostProcessor 的方法为;void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; // 因此BeanDefinitionRegistryPostProcessors,它能够咱们介入,改变Bean的一些定义信息 Set<String> processedBeans = new HashSet<>(); // 只有此beanFactory 是BeanDefinitionRegistry 才能执行BeanDefinitionRegistryPostProcessor,才能修改Bean的定义嘛~ if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; // 此处安放了两个容器,一个装载普通的BeanFactoryPostProcessor // 另一个装载和Bean定义有关的 BeanDefinitionRegistryPostProcessor // 另外都是LinkedList,因此执行顺序和set进去的顺序是保持同样的 List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>(); // 这里是咱们本身的set进去的,若没set,这里就是空(如果Sprng容器里的,下面会处理,见下面) // 今后处能够看出,咱们手动set进去的,最最最最有限执行的 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // 这里执行post方法,而后而后吧它缓冲起来了,放在了registryProcessors里 registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { // 缓冲起来常规的处理器 regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. // 接下来,就是去执行Spring容器里面的一些PostProcessor了。他们顺序doc里也写得很清楚: // 先执行实现了PriorityOrdered接口的,而后是Ordered接口的,最后执行剩下的 List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. // 先从容器中拿出来全部的BeanDefinitionRegistryPostProcessor 而后先执行PriorityOrdered // 本例中有一个这个类型的处理器:ConfigurationClassPostProcessor(显然是处理@Configuration这种Bean的) // 至于这个Bean是何时注册进去的,前面有。在loadBeanDefinitions()初始化AnnotatedBeanDefinitionReader的时候调用的AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)方法的时候,注册了6个Bean String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // processedBeans也顺带保存了一份,保存的是bean的Name哦~ currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } // 排序 sortPostProcessors(currentRegistryProcessors, beanFactory); // 此处缓冲起来(须要注意的是,是排序后,再放进去的 这样是最好的) registryProcessors.addAll(currentRegistryProcessors); // 这个方法很简单,就是吧currentRegistryProcessors里面全部的处理器for循环一个个的执行掉(本处只有ConfigurationClassPostProcessor,详见个人另外一篇专门博文讲解) invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 此处把当前持有的执行对象给清空了,须要注意。以方便装载后续执行的处理器们 currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. // 此处逻辑彻底同上 处理实现Order接口的RegistryProcessors postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. // 最后执行,两个排序接口都没有实现的BeanDefinitionRegistryPostProcessor们,而且也缓存起来 boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. // 如今,这里很明显:去执行BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法 // 以及 顶层接口BeanFactoryPostProcessor的postProcessBeanFactory方法 // 咱们当前环境regularPostProcessors长度为0.registryProcessors有一个解析@Configuration的处理器 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. // 如果普通的Bean工厂,就直接执行set进来的后置处理器便可(由于容器里就没有其它Bean定义了) invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // 下面就是开始执行BeanFactoryPostProcessor 基本也是按照上面的顺序来执行的 // 上面9个Bean,咱们知道 也就ConfigurationClassPostProcessor是实现了此接口的。所以本环境下,只有它了,而且它在上面还已经执行了 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { // 这里面注意,已经执行过的后置处理器,就不要再执行了 if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); }
ConfigurationClassPostProcessor
处理器解析: 【小家Spring】Spring解析@Configuration注解的处理器:ConfigurationClassPostProcessor(ConfigurationClassParser)
postProcessBeanDefinitionRegistry和postProcessBeanFactory
方法:
二者都存在于BeanDefinitionRegistryPostProcessor接口中,代表其既能够自定义BeanDefinition并注册进容器中也能够对beanFactory的修改
那为何逻辑要先执行postProcessBeanDefinitionRegistry而后在执行postProcessBeanFactory呢?
由于postProcessBeanDefinitionRegistry是用来建立bean定义的,而postProcessBeanFactory是修改BeanFactory,固然postProcessBeanFactory也能够修改bean定义的。为了保证在修改以前全部的bean定义的都存在,因此优先执行postProcessBeanDefinitionRegistry。如不是以上顺序,会出先再修改某个bean定义的报错,由于此bean定义的尚未被建立。
至此,invokeBeanFactoryPostProcessors(beanFactory)
这一步就完成了。这一步主要作了:
这里注册Bean定义的时候有个小细节:咱们都知道Spring支持到了FactoryBean的模式,因此这里若是发现注册的Bean为FactoryBean类型的话,会把本身以及getObject()出来的对象的Bean定义都注册上去。而且FactoryBean的名称为:beanName = FACTORY_BEAN_PREFIX + beanName; 这一点须要注意
上面5个步骤,已经Bean工厂彻底准备好了,而且也注册好了全部的Bean的定义信息(此时Bean还并无建立)。也完成了对配置文件的解析,能够说Spring IOC容器的大的准备工做已经完成了,在接下来的一篇博文里,会详细讲述到对Bean的一些初始化、以及操做~
若群二维码失效,请加微信号(或者扫描下方二维码):fsx641385712。
而且备注:“java入群” 字样,会手动邀请入群