Spring源码阅读(一)-核心要点

一、BeanFactory和ApplicationContext的关系

首先看下类图:
在这里插入图片描述
由上图可知,BeanFactory是ApplicationContex的接口,主要是生成、获取bean;而ApplicationContex又拓展了许多高级特性,比如国际化、访问资源文件、事件发布、AOP等。

二、Spring解决循环依赖的代码位置

AbstractApplicationContext#finishBeanFactoryInitialization
	->DefaultListableBeanFactory#preInstantiateSingletons
		->AbstractBeanFactory#doGetBean
			->DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

三、AOP生成代理的代码位置(Bean实例化之前)

AbstractApplicationContext#finishBeanFactoryInitialization
	->DefaultListableBeanFactory#preInstantiateSingletons
		->AbstractBeanFactory#doGetBean
			->AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
				->AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
					->AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

而AOP是基于AnnotationAwareAspectJAutoProxyCreator类实现的,它又实现了BeanPostProcessor接口,所以当Spring加载这个Bean时会在实例化前调用其postProcessAfterInitialization方法,此方法就是AOP创建代理。具体的调用链如下

AbstractAutoProxyCreator#postProcessAfterInitialization
	->AbstractAutoProxyCreator#createProxy
		->DefaultAopProxyFactory#createAopProxy

DefaultAopProxyFactory#createAopProxy类的代码实现截图如下:
在这里插入图片描述

四、Spring容器实现拓展的重要接口-BeanFactoryPostProcessor

以Spring整合Mybatis为例,Mybatis只定义了mapper接口,无实现类,但spring却可以完成自动注入!这就是通过实现BeanFactoryPostProcessor接口,将mapper接口和mapper.xml文件以MapperFactoryBean的类型注册到Spring中的,当从Spring中获取Mapper接口时,将会调用对应的MapperFactoryBean的getObjects方法,该方法返回值即为对应的MapperProxyFactory创建的MapperProxy动态代理对象。Spring整合Mybatis就是用MapperScannerConfigurer这个类来实现BeanFactoryPostProcessor的,下面是MapperScannerConfigurer类的继承关系图:
在这里插入图片描述
调用链如下:

MapperScannerConfigurer#postProcessBeanDefinitionRegistry
	-> ClassPathMapperScanner#doScan
		-> ClassPathMapperScanner#processBeanDefinitions

接下来再进入ClassPathMapperScanner的processBeanDefinitions方法,看下ClassPathMapperScanner是如何偷梁换柱,将mapper接口和mapper.xml文件以MapperFactoryBean的类型注册到Spring中的!

private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    GenericBeanDefinition definition;
    for (BeanDefinitionHolder holder : beanDefinitions) {
      definition = (GenericBeanDefinition) holder.getBeanDefinition();

      if (logger.isDebugEnabled()) {
        logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() 
          + "' and '" + definition.getBeanClassName() + "' mapperInterface");
      }

      // the mapper interface is the original class of the bean
      // but, the actual class of the bean is MapperFactoryBean
      definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
      /**
        就是此处将Mapper接口Bean的Class类型改成MapperFactoryBean,
        此FactoryBean的getObjects就是生动态代理的地方
      **/
      definition.setBeanClass(this.mapperFactoryBean.getClass());

      definition.getPropertyValues().add("addToConfig", this.addToConfig);

      boolean explicitFactoryUsed = false;
      if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
        definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
        explicitFactoryUsed = true;
      } else if (this.sqlSessionFactory != null) {
        definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
        explicitFactoryUsed = true;
      }

      if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
        if (explicitFactoryUsed) {
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
        }
        definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
        explicitFactoryUsed = true;
      } else if (this.sqlSessionTemplate != null) {
        if (explicitFactoryUsed) {
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
        }
        definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
        explicitFactoryUsed = true;
      }

      if (!explicitFactoryUsed) {
        if (logger.isDebugEnabled()) {
          logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
        }
        definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
      }
    }
  }

五、AbstractApplicationContext的onRefresh()方法

AbstractApplicationContext的onRefresh()方法是个空的模板方法,并没有具体的业务逻辑。而在springboot中其子类EmbeddedWebApplicationContext重写了该方法,springboot内置的容器(如Tomcat)正是在此方法中创建的!
先看下类的继承关系:
在这里插入图片描述
调用链如下:

AbstractApplicationContext#refresh
	->AbstractApplicationContext#onRefresh
		->EmbeddedWebApplicationContext#onRefresh
			->EmbeddedWebApplicationContext#createEmbeddedServletContainer
				->TomcatEmbeddedServletContainerFactory#getEmbeddedServletContainer

接下来再进入TomcatEmbeddedServletContainerFactory#getEmbeddedServletContainer()方法看下Tomcat是如何创建的。

@Override
	public EmbeddedServletContainer getEmbeddedServletContainer(
			ServletContextInitializer... initializers) {
		Tomcat tomcat = new Tomcat();
		File baseDir = (this.baseDirectory != null) ? this.baseDirectory
				: createTempDir("tomcat");
		tomcat.setBaseDir(baseDir.getAbsolutePath());
		Connector connector = new Connector(this.protocol);
		tomcat.getService().addConnector(connector);
		customizeConnector(connector);
		tomcat.setConnector(connector);
		tomcat.getHost().setAutoDeploy(false);
		configureEngine(tomcat.getEngine());
		for (Connector additionalConnector : this.additionalTomcatConnectors) {
			tomcat.getService().addConnector(additionalConnector);
		}
		prepareContext(tomcat.getHost(), initializers);
		return getTomcatEmbeddedServletContainer(tomcat);
	}

六、AbstractApplicationContext#finishRefresh()方法

Spring容器已经大致刷新完成,此时会调用AbstractApplicationContext#publishEvent(ApplicationEvent)方法进行上下文刷新完成事件广播,Dubbo的服务暴露就是在此时执行的!

我们知道,< dubbo:service > 标签会被解析成 ServiceBean,ServiceBean 实现了 ApplicationListener,在 Spring 容器初始化的时候会调用 onApplicationEvent 方法。ServiceBean 重写了 onApplicationEvent 方法,实现了服务暴露的功能。
ServiceBean#onApplicationEvent

public void onApplicationEvent(ContextRefreshedEvent event) {
	if (!isExported() && !isUnexported()) {
		if (logger.isInfoEnabled()) {
			logger.info("The service ready on spring started. service: " + getInterface());
		}
		
		// 暴露服务
		export();
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值