一、代码实例

  如之前介绍的,spring中ioc是它最为核心的模块,前边花了大量时间分析spring的bean工厂和他如何生成bean,可是在我们实际应用中,很少直接使用beanFactory,因为spring提供了更好用的ApplicationContext接口,使用方法和bean工厂基本一致

  1. ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
  2. Person person=(Person)context.getBean("person");
  3. person.sayHello();

  那么我们来看下源代码中,我们ClassPathXmlApplicationContext为目标,分析它做了哪些工作。

二、源码分析

  1、进入ClassPathXmlApplicationContext,我们可以看到他提供了各种重构方法,其中配置文件路径可以支持:字符串,可变字符串,数组

  1. public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
  2. this(new String[] {configLocation}, true, null);
  3. }
  4. public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
  5. this(configLocations, true, null);
  6. }
  7. public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
  8. this(configLocations, true, parent);
  9. }
  10. public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
  11. this(configLocations, refresh, null);
  12. }

  2、进入refresh方法,首先竹本refresh环境,

  1. protected void prepareRefresh() {
  2. this.startupDate = System.currentTimeMillis();
  3. this.closed.set(false);
  4. this.active.set(true);
  5.  
  6. if (logger.isInfoEnabled()) {
  7. logger.info("Refreshing " + this);
  8. }
  9.  
  10. // Initialize any placeholder property sources in the context environment
  11. initPropertySources();
  12.  
  13. // Validate that all properties marked as required are resolvable
  14. // see ConfigurablePropertyResolver#setRequiredProperties
  15. getEnvironment().validateRequiredProperties();
  16.  
  17. // Allow for the collection of early ApplicationEvents,
  18. // to be published once the multicaster is available...
  19. this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
  20. }

  3、调用ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

  1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  2. refreshBeanFactory();
  3. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  4. if (logger.isDebugEnabled()) {
  5. logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
  6. }
  7. return beanFactory;
  8. }

  4、调用refreshBeanFactory方法,可以看到里边的几个步骤

  a)生产beanfactory,如果有父类,继承父类

  b)设置序列化id

  c)customizeBeanFactory,暂时不知道用处

  d)loadBeanDefinitions(beanFactory)最终调用了loadBeanDefinitions(beanDefinitionReader)方法

  可见在此步骤已经完成了对xml文件的读取,并解析为最终的beanDefinition

  1. protected final void refreshBeanFactory() throws BeansException {
  2. if (hasBeanFactory()) {
  3. destroyBeans();
  4. closeBeanFactory();
  5. }
  6. try {
  7. DefaultListableBeanFactory beanFactory = createBeanFactory();
  8. beanFactory.setSerializationId(getId());
  9. customizeBeanFactory(beanFactory);
  10. loadBeanDefinitions(beanFactory);
  11. synchronized (this.beanFactoryMonitor) {
  12. this.beanFactory = beanFactory;
  13. }
  14. }
  15. catch (IOException ex) {
  16. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
  17. }
  18. }

  5、prepareBeanFactory设置各种BeanFactory的参数

  6、invokeBeanFactoryPostProcessors调用BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的方法

  7、查找是否有initMessageSource为id的bean,如果没有,创建默认的

  8、查找是否有id为applicationEventMulticaster的bean,如果没有,创建默认,设置为congtext的applicationEventMulticaster

  1. protected void initApplicationEventMulticaster() {
  2. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  3. //查找是否包含名为applicationEventMulticaster的bean,如果没有,创建默认的
  4. if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
  5. this.applicationEventMulticaster =
  6. beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
  7. if (logger.isDebugEnabled()) {
  8. logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
  9. }
  10. }
  11. else {
  12. this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
  13. beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
  14. if (logger.isDebugEnabled()) {
  15. logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
  16. APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
  17. "': using default [" + this.applicationEventMulticaster + "]");
  18. }
  19. }
  20. }

  9、查找注册的ApplicationListener,设置到applicationEventMulticaster中

  1. protected void registerListeners() {
  2. // Register statically specified listeners first.
  3. //查找手动设置的ApplicationListener,设置到applicationEventMulticaster中
  4. for (ApplicationListener<?> listener : getApplicationListeners()) {
  5. getApplicationEventMulticaster().addApplicationListener(listener);
  6. }
  7.  
  8. // Do not initialize FactoryBeans here: We need to leave all regular beans
  9. // uninitialized to let post-processors apply to them!
  10. //根据beanType查询ApplicationListener,设置到applicationEventMulticaster中
  11. String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
  12. for (String listenerBeanName : listenerBeanNames) {
  13. getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  14. }
  15.  
  16. // Publish early application events now that we finally have a multicaster...
  17. Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
  18. //查询是否有需要立即通知的事件,进行通知
  19. this.earlyApplicationEvents = null;
  20. if (earlyEventsToProcess != null) {
  21. for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
  22. getApplicationEventMulticaster().multicastEvent(earlyEvent);
  23. }
  24. }
  25. }

  10、查找是否有id为conversionService的bean,如果有,设置进beanFactory

  1. //查找是否有id为conversionService的bean,如果有,设置进beanFactory
  2. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
  3. beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
  4. beanFactory.setConversionService(
  5. beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
  6. }

  11、查找是否有embeddedValueResolvers,值的解析器,没有默认注入string解析

  1. //查找是否有embeddedValueResolvers,值的解析器,没有默认注入string解析
  2. if (!beanFactory.hasEmbeddedValueResolver()) {
  3. beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
  4. @Override
  5. public String resolveStringValue(String strVal) {
  6. return getEnvironment().resolvePlaceholders(strVal);
  7. }
  8. });
  9. }

  12、查找类型为LoadTimeWeaverAware的解析,有的话进行获取,并没有进一步使用,应该只是起到初始化作用

  1. //查找类型为LoadTimeWeaverAware的解析,有的话进行获取,并没有进一步使用,应该只是起到初始化作用
  2. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
  3. for (String weaverAwareName : weaverAwareNames) {
  4. getBean(weaverAwareName);
  5. }

  13、进入preInstantiateSingletons方法,初始化所有的bean

  1. for (String beanName : beanNames) {
  2. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  3. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
  4. //判断是否工厂bean
  5. if (isFactoryBean(beanName)) {
  6. final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
  7. boolean isEagerInit;
  8. if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
  9. isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
  10. @Override
  11. public Boolean run() {
  12. return ((SmartFactoryBean<?>) factory).isEagerInit();
  13. }
  14. }, getAccessControlContext());
  15. }
  16. else {
  17. isEagerInit = (factory instanceof SmartFactoryBean &&
  18. ((SmartFactoryBean<?>) factory).isEagerInit());
  19. }
  20. if (isEagerInit) {
  21. getBean(beanName);
  22. }
  23. }
  24. else {
  25. //进行实例化
  26. getBean(beanName);
  27. }
  28. }
  29. }

  14、已经初始化的bean,并且继承了SmartInitializingSingleton接口,执行它的afterSingletonsInstantiated方法

  1. //已经初始化的bean,并且继承了SmartInitializingSingleton接口,执行它的afterSingletonsInstantiated方法
  2. for (String beanName : beanNames) {
  3. Object singletonInstance = getSingleton(beanName);
  4. if (singletonInstance instanceof SmartInitializingSingleton) {
  5. final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
  6. if (System.getSecurityManager() != null) {
  7. AccessController.doPrivileged(new PrivilegedAction<Object>() {
  8. @Override
  9. public Object run() {
  10. smartSingleton.afterSingletonsInstantiated();
  11. return null;
  12. }
  13. }, getAccessControlContext());
  14. }
  15. else {
  16. smartSingleton.afterSingletonsInstantiated();
  17. }
  18. }
  19. }

  15、调用finishRefresh,完成bean的刷新,第一步initLifecycleProcessor初始化bean的生命后周期bean

  1. protected void initLifecycleProcessor() {
  2. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  3. //获取id为lifecycleProcessor的bean,如果没有,创建默认的
  4. if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
  5. this.lifecycleProcessor =
  6. beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
  7. if (logger.isDebugEnabled()) {
  8. logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
  9. }
  10. }
  11. else {
  12. DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
  13. defaultProcessor.setBeanFactory(beanFactory);
  14. this.lifecycleProcessor = defaultProcessor;
  15. beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
  16. if (logger.isDebugEnabled()) {
  17. logger.debug("Unable to locate LifecycleProcessor with name '" +
  18. LIFECYCLE_PROCESSOR_BEAN_NAME +
  19. "': using default [" + this.lifecycleProcessor + "]");
  20. }
  21. }
  22. }

  16、getLifecycleProcessor().onRefresh()方法,启动特定bean

  1. private void startBeans(boolean autoStartupOnly) {
  2. Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
  3. //获取所有继承了Lifecycle的SmartLifecycle,并且自动启动且phase不为空,那么执行start方法
  4. Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
  5. for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
  6. Lifecycle bean = entry.getValue();
  7. if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
  8. int phase = getPhase(bean);
  9. LifecycleGroup group = phases.get(phase);
  10. if (group == null) {
  11. group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
  12. phases.put(phase, group);
  13. }
  14. group.add(entry.getKey(), bean);
  15. }
  16. }
  17. if (phases.size() > 0) {
  18. List<Integer> keys = new ArrayList<Integer>(phases.keySet());
  19. Collections.sort(keys);
  20. for (Integer key : keys) {
  21. phases.get(key).start();
  22. }
  23. }
  24. }

  17、广播容器刷新事件publishEvent(new ContextRefreshedEvent(this))

  1. protected void publishEvent(Object event, ResolvableType eventType) {
  2. Assert.notNull(event, "Event must not be null");
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Publishing event in " + getDisplayName() + ": " + event);
  5. }
  6.  
  7. // Decorate event as an ApplicationEvent if necessary
  8. ApplicationEvent applicationEvent;
  9. if (event instanceof ApplicationEvent) {
  10. applicationEvent = (ApplicationEvent) event;
  11. }
  12. else {
  13. applicationEvent = new PayloadApplicationEvent<Object>(this, event);
  14. if (eventType == null) {
  15. eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
  16. }
  17. }
  18.  
  19. // Multicast right now if possible - or lazily once the multicaster is initialized
  20. if (this.earlyApplicationEvents != null) {
  21. //如果有预制行添加到预制行,预制行在执行一次后被置为null,以后都是直接执行
  22. this.earlyApplicationEvents.add(applicationEvent);
  23. }
  24. else {
  25. //广播event时间
  26. getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
  27. }
  28.  
  29. // Publish event via parent context as well...
  30. //父bean同样广播
  31. if (this.parent != null) {
  32. if (this.parent instanceof AbstractApplicationContext) {
  33. ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
  34. }
  35. else {
  36. this.parent.publishEvent(event);
  37. }
  38. }
  39. }

  18、到此,我们完成了整个初始化过程,获取bean时候,流程基本不变

三、总结

  我们可以看到,与beanfactory相比,context有以下特点:

  1、在基本的解析文件生成beanDefinition过程其实两者是一致的,都是解析了xml的配置后生成了配置文件放到了beanDefinitionMap中

  2、在beanFactory中的,bean是在第一次getBean的时候进行生成,所以配置lazy-init延迟加载并不会起作用,因为全部bean都是延迟加载的。在context中,会在解析完成后的preInstantiateSingletons方法中调用getBean初始化所有的非lazy-init且单例模式的bean

  3、在context中内置了许多的bean,他们要求开发者必须按照系统约定的命名规则进行命名,这样可以在系统内部组成特定的功能,如果开发者没有定义这些bean,系统也会默认生成一个bean,这些bean主要有:messageSource、applicationEventMulticaster、conversionService、embeddedValueResolvers、lifecycleProcessor,也有一些指定了接口实现的bean如:LoadTimeWeaverAware、SmartInitializingSingleton。这些类完善了bean的整个流程,使得ioc容器可以读取配置文件,管理通知,bean生命周期等

[spring源码学习]七、IOC源码-Context的更多相关文章

  1. Spring Ioc源码分析系列--Ioc源码入口分析

    Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...

  2. spring cloud深入学习(四)-----eureka源码解析、ribbon解析、声明式调用feign

    基本概念 1.Registe 一一服务注册当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址.端口.运行状况指标的Uri.主页地址 ...

  3. 【 js 基础 】【 源码学习 】backbone 源码阅读(一)

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...

  4. 【 js 基础 】【 源码学习 】backbone 源码阅读(二)

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(source-code-study)进行参考交流,有详细的源码注释,以及知识总结,同时 ...

  5. 【 js 基础 】【 源码学习 】backbone 源码阅读(三)浅谈 REST 和 CRUD

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...

  6. go 源码学习之---Tail 源码分析

    已经有两个月没有写博客了,也有好几个月没有看go相关的内容了,由于工作原因最近在做java以及大数据相关的内容,导致最近工作较忙,博客停止了更新,正好想捡起之前go的东西,所以找了一个源码学习 这个也 ...

  7. 【 js 基础 】【 源码学习 】backbone 源码阅读(三)

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...

  8. Jetty源码学习-编译Jetty源码二三事

    工作小几个月了,JDK基础和web应用框架学的的差不多了,开始学习Jetty源码,费了小半天才编译成功,把自己拆过的坑记录下来. 编译前的环境: MAVEN 3.3.Eclips eLuna Serv ...

  9. Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory

    从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...

随机推荐

  1. iOS优秀博客收录

    原文链接:http://ju.outofmemory.cn/entry/105297 唐巧 王巍 破船之家 NSHipster Limboy 无网不剩 念茜的博客 Xcode Dev Ted's Ho ...

  2. [从产品角度学excel 04]-单元格的“衣服”

    忘记发这里了..补发一下 这是<从产品角度学EXCEL>系列——单元格篇. 前言请看: 0 为什么要关注EXCEL的本质 1 excel是怎样运作的 2 EXCEL里的树形结构 3 单元格 ...

  3. JS事件的三种方式

    1.直接在元素上绑定回调函数 <button id="btn" onclick="clickBtn()">click me</button&g ...

  4. SQL Server中查询数据库及表的信息语句

    /* -- 本文件主要是汇总了 Microsoft SQL Server 中有关数据库与表的相关信息查询语句. -- 下面的查询语句中一般给出两种查询方法, -- A方法访问系统表,适应于SQL 20 ...

  5. 关于JS事件的几点总结

    1.理解事件(2点) 事件行为本身:没有给事件绑定方法事件也是一直存在的,当触发行为的时候,也对触发对应的行为,只不过由于没有绑定事件,导致没有任何事件发生: 事件绑定:给元素绑定一个方法:触发行为, ...

  6. 使用CSS隐藏HTML元素的4种常用方法

    现在的网页设计越来越动态化,我们经常需要隐藏某些元素,在特定的时候才显示它们.我们通常可以使用4种方法来隐藏和显示元素. 这4种显示和隐藏元素的技术各自有它们自己的优点的缺点,下面来举例说明. 在这篇 ...

  7. C#微信公众号开发系列教程二(新手接入指南)

    http://www.cnblogs.com/zskbll/p/4093954.html 此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可 ...

  8. Gerrit增加SSL证书

    在http的基础上增加SSL 配置gerrit.config文件 [gerrit] basePath = git canonicalWebUrl = https://172.16.99.212/ .. ...

  9. pg gem 安装(postgresql94)

    使用下面命令安装报错 gem install pg 错误: [root@AS-test middle_database]# gem install pgBuilding native extensio ...

  10. Windows10系统如何更改程序的默认安装目录?

    Windows10系统如何更改程序的默认安装目录? 在Windows10系统的使用中,软件程序的默认安装目录是:C:\Program Files\...或者C:\Program Files(x86)\ ...