Spring加载Bean流程

概要

spring IOC(Inversion Of Control)控制反转,由spring控制bean的生命周期和对象之间的依赖关系。简单说以前是我要对象但是需要我自己去找(new一个对象),现在是我告诉婚介公司(spring容器)我需要一个长得像章子怡,身材像张柏芝,速度像卡洛斯,技术像罗纳尔多的对象,然后婚介公司(spring容器)直接把我需要的对象提供给我。对象之间的依赖关系spring是以DI(依赖注入)的方式实现的,DI实际上就是我把你需要的对象直接送到你面前,至于这个对象怎么来的,什么时候来的我不需要关心。

流程图

在这里插入图片描述

流程分析

spring提供了两种IOC容器ApplicationContext和BeanFactory,ApplicationContext是BeanFactory的子类,是更强大的BeanFactory。 BeanFactory是基础,它提供的API满足了Spring对bean的管理。而ApplicationContext是扩展,以BeanFactory为主线,扩展了国际化、资源、事件等多条支线,这些支线是以bean的管理为基础。

  1. 容器(tomcat)启动后,调用spring的contextloaderListener监听,开启spring的生命周期。
  2. 初始化上下文ApplicationContext,初始化beanfactory。
  3. 通过beanDefinitionReader加载beanDefinition,并通过beanDefinitionRegistry将beanDefinition注册到beanFactory中。如果是xml配置文件,通过dom方式读取xml,如果是注解方式根据base-package路径通过asm技术将class文件解析成spring的元数据metadata,最终组装成beanDefinition注册到beanFactory中。
  4. 对beanFactory进行填充,主要包括填充类加载器、注册beanPostProcessor(执行aware注入和注册Listener的beanPostProcessor)。
  5. 注册并执行beanFactoryPostProcessor,这也是在bean初始化前的最后一道工序,在我们的系统中可以实现beanFactoryPostProcessor接口对beanDefinition进行修改,但要注意此时的bean并没有实例化。例如,PropertyPlaceholderConfigurer是beanFactoryPostProcessor的子类,主要负责将beanDefinition从xml文件中加载进来的占位符形式的参数值,使用properties文件中的实际值进行替换。
  6. 注册beanPostProcessor,将系统中所有实现beanPostProcessor接口的类全部实例化并注册到现beanFactory中。
  7. 初始化ApplicationEventMulticaster,如果外部没有定义ApplicationEventMulticaster,那么默认初始化SimpleApplicationEventMulticaster,并注册到applicationContext。
  8. 检测如果有实现了applicationListener接口的bean,则将该bean注册到ApplicationEventMulticaster中。
  9. 初始化bean,保存属性值、依赖的注入。
  10. 执行各种aware的注入,例如BeanNameAware、ApplicationContextAware等。
  11. 执行前置处理器,BeanPostProcessor的postProcessBeforeInitialization方法。
  12. 执行InitializingBean的afterPropertiesSet方法。
  13. 执行init-method配置。
  14. 执行后置处理器,BeanPostProcessor的postProcessAfterInitialization方法。
  15. 然后就是bean的使用了
  16. 最后是bean的销毁,DisposableBean的destroy方法。
  17. 然后是执行destroy-method配置。

源码分析

容器(tomcat)启动后,调用spring的contextloaderListener的contextInitialized方法

@Override
   public void contextInitialized(ServletContextEvent event) {
   	initWebApplicationContext(event.getServletContext());
   }

initWebApplicationContext中的主要跟踪createWebApplicationContext和configureAndRefreshWebApplicationContext方法,其中createWebApplicationContext默认创建了XmlWebApplicationContext上下文对象。

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
		Class<?> contextClass = determineContextClass(sc);
		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
			throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
					"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
		}
		return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
	}

configureAndRefreshWebApplicationContext方法中调用了AbstractApplicationContext类中的refresh方法。
其中obtainFreshBeanFactory方法主要加载和注册BeanDefinition。

beanDefinitionReader加载BeanDefinition的代码由于链路太长,代码也比较复杂,这里就不展示了。

@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}

invokeBeanFactoryPostProcessors方法主要是加载并执行BeanFactoryPostProcessor的,主要流程就是先执行实现了BeanDefinitionRegistry接口的BeanFactoryPostProcessor实现类,然后实现了priorityOrder接口的BeanFactoryPostProcessor,然后是实现Ordered接口的BeanFactoryPostProcessor,最后是没有实现Ordered接口的BeanFactoryPostProcessor。

registerBeanPostProcessors方法也是按照上面的顺序注册BeanPostProcessor的。

initApplicationEventMulticaster方法初始化ApplicationEventMulticaster,然后注册事件

protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
						"': using default [" + this.applicationEventMulticaster + "]");
			}
		}
	}



protected void registerListeners() {
		// Register statically specified listeners first.
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let post-processors apply to them!
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}
	}

最后,通过finishBeanFactoryInitialization方法根据BeanDefinition信息对bean进行初始化,并对bean的依赖对象进行注入,以及对扩展接口的执行。首先执行的是各种Aware的注入,然后执行前置处理器,InitializingBean的afterPropertiesSet方法,init-method配置,至此Bean就完全创建完成。

使用的设计模式

  1. BeanFactory使用工厂模式。
  2. 在解析xml时,NameSpaceHandlerResolver,根据命名空间uri获取NameSpaceHandler,使用了策略模式。BeanDefinitionParser,根据元素名称获取BeanDefinitionParser,使用了策略模式。
  3. 在解析元数据注解时,SimpleMetadataReader的构造函数中使用了访问者模式,AnnotationMetadataReadingvisitor作为访问者,ClassReader作为被访问的元素。

spring中使用了大量的设计模式,我们还是要掌握一些设计模式,不管是阅读源码还是对自己代码的设计以及代码的扩展性都是有帮助的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值