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之前的准备工作就完成了。