在分析Spring相关源码时,或者优化Spring启动过程时,可能能够用到的一些调试的断点的位置。
容器的创建
- Spring
ApplicationContext容器类型为:XmlWebApplicationContext,来自web.xml文件中配置的ContextLoaderListener,默认类型配置在ContextLoader.properties中
BeanFactory容器类型为:DefaultListableBeanFactory
断点位置:
1 | protected WebApplicationContext createWebApplicationContext(ServletContext sc) {} |
- SpringMVC
ApplicationContext容器类型为:XmlWebApplicationContext,来自web.xml文件中配置的DispatcherServlet
BeanFactory容器类型为:DefaultListableBeanFactory
断点位置:
1 | protected WebApplicationContext initWebApplicationContext() {} |
- SpringBoot
ApplicationContext容器类型为:
SpringBoot 1.x : AnnotationConfigEmbeddedWebApplicationContext
SpringBoot 2.x : AnnotationConfigServletWebServerApplicationContext
BeanFactory容器类型为:DefaultListableBeanFactory
断点位置:
1 | protected ConfigurableApplicationContext createApplicationContext() {} |
看容器中所有的Bean
由于在AbstractApplicationContext
的finishBeanFactoryInitialization()方法中会初始化剩余的bean,因此在这一步的下一行finishRefresh()
打断点就能看到所有的bean了。
1 | public void refresh() throws BeansException, IllegalStateException { |
在beanFactory变量中,最重要的两个变量是“singletonObjects
”和“beanDefinitionMap
”。
singletonObjects保存的是整个Spring容器中 id -> 实例 的键值对,是最终的全体单例保存的地方。
beanDefinitionMap保存的是 id -> bean定义 的键值对,保存了Spring扫描到的所有Bean定义。
重复Bean和Bean的覆盖
当同一个xml文件
中定义了id相同的bean时,Spring会启动失败,并抛异常。这是在xml文件读取时完成的,同一个空间中不允许相同的id。
1 | protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement){} |
当不同的xml文件
中定义了名字一样的bean的时候,后被扫描到的bean会将先扫描到的bean覆盖掉,并输出以下日志:
2019-04-12 16:50:32.784 main [INFO] o.s.b.f.s.DefaultListableBeanFactory (DefaultListableBeanFactory.java:828 Overriding bean definition for bean ‘ExceptionDeclaration’ with a different definition: replacing [Genericbean: class []; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0;autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null;destroyMethodName=null; defined in URL []] with [Root bean: class [null]; scope=; abstract=false;lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false;factoryBeanName=enableThriftServerPublish.ThriftServerPublishConfiguration;factoryMethodName=ExceptionDeclaration; initMethodName=null; destroyMethodName=(inferred); defined in classpath resource []]
覆盖的操作是在bean注册时完成的,断点位置:
1 | public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) |