天天看点

sprint源码分析(3)——Bean的预加载

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   this();
   register(annotatedClasses); 
   refresh();
}
           

        在sprint的源码分析(1)(2)中,我们分析了this()和register(),到目前为止,spring已经加载了一些必要的资源,接下来就是最终要的refresh()方法。

        Spring上下文刷新始于refresh()方法。

@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.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);
      ......

   }
}
           

        startupShutdownMonitor是一个object,是refresh方法和destory方法公用的一个监视器,避免两个方法同时执行。

protected void prepareRefresh() {
   this.startupDate = System.currentTimeMillis();
   this.closed.set(false);
   this.active.set(true);

   if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
   }

   // Initialize any placeholder property sources in the context environment
   initPropertySources();

   // Validate that all properties marked as required are resolvable
   // see ConfigurablePropertyResolver#setRequiredProperties
   getEnvironment().validateRequiredProperties();

   // Allow for the collection of early ApplicationEvents,
   // to be published once the multicaster is available...
   this.earlyApplicationEvents = new LinkedHashSet<>();
}
           

        prepareRefresh方法首先设置容器启动时间和启动标志字段,initPropertySources是个空方法,不执行任何操作,getEnvironment().validateRequiredProperties方法主要是为了验证requiredProperties中的key是否都能找到对应的value值。如果找不到,就会抛出异常。

        obtainFreshBeanFactory() 获得BeanFactory,BeanFactory在AbstractApplicationContext类初始化的时候已经初始化为DefaultListableBeanFactory。

public GenericApplicationContext() {
   this.beanFactory = new DefaultListableBeanFactory();
}
           

        如果还有印象的话,这个beanFactory在sping源码解析(1)(2)中分别添加了内置的注解处理器和自定义的注解配置类。当前要获得的就是这个beanFactory。

        obtainFreshBeanFactory()在通过注解或者通过XML加载Bean时是不同的实现方式,在通过xml加载配置的时候,它会将配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了。但是我们这里是通过注解来加载Bean定义的,所以看源码就会发现,这句话其实没干什么事。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}
           

        refreshBeanFactory是抽象类 AbstractApplicationContext的一个抽象方法,有AbstractRefreshableApplicationContext和GenericApplicationContext这两个子类实现了这个方法。这里根据继承关系判断调用的是GenericApplicationContext的方法。

@Override
protected final void refreshBeanFactory() throws IllegalStateException {
   if (!this.refreshed.compareAndSet(false, true)) {
      throw new IllegalStateException(
            "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
   }
   this.beanFactory.setSerializationId(getId());
}
           

        这个方法很简单,就是判断applicaitonContext是否已经刷新过,如果已经刷新,则报错“不支持多次刷新”。然后为beanFactory设置一个唯一的序列号。之后就是打日志和返回beanFactory。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		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 interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		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());
		}
	}
           

        第3行为BeanFactory设置了一个类加载器,BeanFactory 需要加载类,也就需要类加载器,是一个AppClassLoader。

        第4行为BeanFactory设置了一个BeanExpressionResolver。从代码看来,StandardBeanExpressionResolver是用来解析EL表达式的,比如配置文件或者@Value("#{...}")等使用。

public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
   this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
}
           

        第5行代码是注册属性编辑器ResourceEditorRegistrar。ResourceEditorRegistrar注册的属性编辑器如下:

@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
   ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
   doRegisterEditor(registry, Resource.class, baseEditor);
   doRegisterEditor(registry, ContextResource.class, baseEditor);
   doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
   doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
   doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
   doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
   doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
   doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));

   ClassLoader classLoader = this.resourceLoader.getClassLoader();
   doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
   doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
   doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));

   if (this.resourceLoader instanceof ResourcePatternResolver) {
      doRegisterEditor(registry, Resource[].class,
            new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
   }
}
           

        具体研究下,发现这些Editor都继承了PropertyEditorSupport这个类,并且重写其setAsText(String source)方法,通过这个方法将输入的字符串转换成我们期望的数据类型。

例如InputStreamEditor这个属性编辑器,可以将spring配置文件中,用字符串表示的文件路径,转成Resource资源类,注入到bean的对应属性中。

        第8行代码为BeanFactory加入了一个BeanPostProcessor,我们知道BeanPostProcessor是在Bean的初始化前后做一些事情的, ApplicationContextAwareProcessor就是因为某些类需要加载spring的上下文,这是就要通过ApplicationContextAwareProcessor的postProcessBeforeInitialization方法注入applicationContext或者是beanFactory。具体类如下所示。

private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}
           

        这些类在经过这段代码后,就拿到了spring的上下文,可以操作spring管理的Bean对象。

        第9-14行为beanFactory添加了一些接口,这些接口在后续处理的时候不会自动装配,而是通过其他方式解析Application上下文注册依赖,比如EnvironmentAware等接口都是在第8行代码中ApplicationContextAwareProcessor的postProcessBeforeInitialization方法单独处理的。

        第18-21行是为特殊的几个 bean 赋值,如果有 bean 依赖了以下几个,会注入这边相应的值。之前已经讲过,BeanFactory在AbstractApplicationContext类初始化的时候已经初始化为DefaultListableBeanFactory。所以如果有类依赖了BeanFactory,会将当前持有的DefaultListableBeanFactory注入进去。通过类图可以看到,AnnotationConfigApplicationContext继承了ResourceLoader,ApplicationEventPublisher,ApplicationContext。所以将这些类赋值为this是没有问题的。

@Override
public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
   Assert.notNull(dependencyType, "Dependency type must not be null");
   if (autowiredValue != null) {
      if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
         throw new IllegalArgumentException("Value [" + autowiredValue +
               "] does not implement specified dependency type [" + dependencyType.getName() + "]");
      }
      this.resolvableDependencies.put(dependencyType, autowiredValue);
   }
}
           

        代码执行完毕后,resolvableDependencies中就保存了类名和实例之间的映射,注入的时候可以直接拿来用。

        第24行代码注册了一个BeanPostProcessor,ApplicationListenerDetector。查看这个类的postProcessAfterInitialization方法。

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
   if (bean instanceof ApplicationListener) {
      // potentially not detected as a listener by getBeanNamesForType retrieval
      Boolean flag = this.singletonNames.get(beanName);
      if (Boolean.TRUE.equals(flag)) {
         // singleton bean (top-level or inner): register on the fly
         this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
      }
      else if (Boolean.FALSE.equals(flag)) {
         if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
            // inner bean with other scope - can't reliably process events
            logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                  "but is not reachable for event multicasting by its containing ApplicationContext " +
                  "because it does not have singleton scope. Only top-level listener beans are allowed " +
                  "to be of non-singleton scope.");
         }
         this.singletonNames.remove(beanName);
      }
   }
   return bean;
}
           

        在 bean 实例化后,如果这个bean是 ApplicationListener 的子类,那么将其添加到 listener 列表中,可以理解成:注册事件监听器。

        接着是第27行~第31行,意思是如果自定义的Bean中没有一个名为”loadTimeWeaver”的Bena,则会添加一个LoadTimeWeaverAwareProcessor。这也是一个BeanPostProcessor,这个后处理器只对LoadTimeWeaverAware类型的bean起作用,LTW(Load Time Weaver),即加载期切面织入,是ApsectJ切面织入的一种方式,它通过JVM代理在类加载期替换字节码到达织入切面的目的。至于loadTimeWeaver这个bean,是可以空过@EnableLoadTimeWeaving注解启用的。

        第34-41行spring注册了3个bean,分别是 "environment" ,"systemProperties"以及 "systemEnvironment" 。

        至此,Spring初始化bean之前的准备工作就完成了。

继续阅读