一、基本概念 1.容器相关类图 1.1 容器概览 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 @startuml interface ApplicationContext #Orange extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { } /' ' 1.BeanFactory '/ interface BeanFactory #Orange { } interface AutowireCapableBeanFactory extends BeanFactory { } interface ListableBeanFactory extends BeanFactory { } interface HierarchicalBeanFactory extends BeanFactory { } interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { } interface AliasRegistry { } class SimpleAliasRegistry implements AliasRegistry { } class DefaultSingletonBeanRegistry #LightSalmon extends SimpleAliasRegistry implements SingletonBeanRegistry { } abstract class FactoryBeanRegistrySupport #LightSalmon extends DefaultSingletonBeanRegistry { } abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { } abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { } interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory { } class DefaultListableBeanFactory #LightSalmon extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { } class XmlBeanFactory #Cyan extends DefaultListableBeanFactory { } /' ' 2.ApplicationEventPublisher、EnvironmentCapable、MessageSource '/ interface ApplicationEventPublisher { } interface EnvironmentCapable { } interface MessageSource { } /' ' 3.ResourceLoader '/ interface ResourceLoader { } interface ResourcePatternResolver extends ResourceLoader { } class DefaultResourceLoader implements ResourceLoader { } 'note left of ApplicationContext: On last defined class /' ' 4.ApplicationContext '/ interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable { } interface Lifecycle { } interface Closeable extends AutoCloseable { } interface AutoCloseable { } abstract class AbstractApplicationContext #LightSalmon extends DefaultResourceLoader implements ConfigurableApplicationContext { } abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { } abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext implements BeanNameAware, InitializingBean { } interface InitializingBean { } interface BeanNameAware extends Aware { } interface Aware { } /' ' 4.1 AbstractXmlApplicationContext '/ abstract class AbstractXmlApplicationContext #LightSalmon extends AbstractRefreshableConfigApplicationContext { } class ClassPathXmlApplicationContext #Cyan extends AbstractXmlApplicationContext { } class FileSystemXmlApplicationContext #Cyan extends AbstractXmlApplicationContext { } /' ' 4.2 AbstractRefreshableWebApplicationContext '/ abstract class AbstractRefreshableWebApplicationContext #LightSalmon extends AbstractRefreshableConfigApplicationContext implements ConfigurableWebApplicationContext, ThemeSource { } interface ThemeSource { } class XmlWebApplicationContext #Cyan extends AbstractRefreshableWebApplicationContext { } interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext { } interface WebApplicationContext extends ApplicationContext { } class GenericApplicationContext #LightSalmon extends AbstractApplicationContext implements BeanDefinitionRegistry { } interface BeanDefinitionRegistry #HotPink extends AliasRegistry { } interface AliasRegistry { } class AnnotationConfigApplicationContext #Cyan extends GenericApplicationContext implements AnnotationConfigRegistry { } interface AnnotationConfigRegistry { } class AnnotationConfigWebApplicationContext #Cyan extends AbstractRefreshableWebApplicationContext implements AnnotationConfigRegistry { } @enduml
BeanFactory 相关
AliasRegistry : 定义对 alias 的简单增删改查
SimpleAliasRegistry :实现了AliasRegistry ,使用map作为 alias 的缓存
SingletonBeanRegistry : 定义对单例的注册及获取
DefaultSingletonBeanRegistry:对接口SingletonBeanRegistry 各方法的实现
FactoryBeanRegistrySupport :在DefaultSingletonBeanRegistry基础上增加了对FactoryBean的特殊处理功能
BeanFactory:定义获取Bean及Bean的各种属性
HierarchicalBeanFactory :在 BeanFactory 定义的功能的基础上增加了对 parentFactory 的支持
ListableBeanFactory :在 BeanFactory 定义的功能的基础上增加了枚举所有Bean实例的能力,预加载所有bean定义(如基于xml的工厂)的BeanFactory实现可能实现了此接口。
ConfigurableBeanFactory :提供配置 BeanFactory 的各种方法
AutowireCapableBeanFactory :提供创建Bean、自动注入、初始化以及应用Bean的后置处理器
ConfigurableListableBeanFactory :大部分的 ListableBeanFactory 都需要实现此接口,在ConfigurableBeanFactory 之上提供了分析和修改Bean定义(忽略依赖类型和接口等)、以及预初始化单例Bean的能力
AbstractBeanFactory :综合 FactoryBeanRegistrySupport 、ConfigurableBeanFactory
AbstractAutowireCapableBeanFactory : 综合 AbstractBeanFactory 并对AutowireCapableBeanFactory 接口进行实现
BeanDefinitionRegistry :定义对BeanDefinition的各种操作
DefaultListableBeanFactory:综合上面所有功能,主要是对Bean注册之后的处理
ApplicationContext
ResourceLoader :策略模式接口,提供获取类加载器,以及获取classpath:
这种URL前缀资源的能力
ResourcePatternResolver :提供了从类路径下获取classpath*:
这种伪URL前缀的资源,与ResourceLoader 的 classpath:
不同的是,它能获取所有匹配的资源,包括jar包中的资源
EnvironmentCapable :提供获取 Environment 能力
MessageSource :策略模式接口,提供消息的参数化和国际化的能力
ApplicationContext :具有获取应用程序组件、继承父容器、通用的资源处理等能力
WebApplicationContext : 提供获取web应用 ServletContext 的能力,与一般的ApplicationContext不同的是,它是具有层次的,每个应用都有一个根上下文,同时每个Servlet有都有其子上下文
ConfigurableApplicationContext :让ApplicationContext具备可配置能力,同时提供加载和刷新配置信息的持久化表示的能力
ConfigurableWebApplicationContext:让 WebApplicationContext 具备可配置能力
AbstractApplicationContext : 模板方法模式,实现了很多ApplicationContext的接口,与普通的BeanFactory不同的是,ApplicationContext 自动注册一些BeanFactory内部定义的Bean,例如,BeanFactoryPostProcessors, BeanPostProcessors, ApplicationListeners
AbstractRefreshableApplicationContext :支持多次调用 ConfigurableApplicationContext 的 refresh 方法,每次调用都将创建一个新的BeanFactory,默认创建的是 DefaultListableBeanFactory 类型的
1.2 DefaultListableBeanFactory 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 @startuml interface BeanFactory #Orange { } interface AutowireCapableBeanFactory extends BeanFactory { } interface HierarchicalBeanFactory extends BeanFactory { } interface ListableBeanFactory extends BeanFactory { } interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { } interface AliasRegistry { } class SimpleAliasRegistry implements AliasRegistry { } class DefaultSingletonBeanRegistry #LightSalmon extends SimpleAliasRegistry implements SingletonBeanRegistry { } abstract class FactoryBeanRegistrySupport #LightSalmon extends DefaultSingletonBeanRegistry { } abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { } abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { } interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory { } class DefaultListableBeanFactory #LightSalmon extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { } interface BeanDefinitionRegistry extends AliasRegistry { } class XmlBeanFactory extends DefaultListableBeanFactory { } @enduml
1.3 二、容器的创建过程 以 ClassPathXmlApplicationContext
的创建过程为例:
1 2 3 4 5 6 7 8 9 10 11 public class ApplicationContextTest { @Test public void testClassPathXmlApplicationContext () { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext ("beanFactoryTest.xml" ); MyTestBean bean = (MyTestBean) applicationContext.getBean("myTestBean" ); Assert.assertEquals("testStr" , bean.getTestStr()); } }
1.流程图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @startuml rectangle "1.项目启动" as startProject file "config.xml/JavaConfig" as configFile frame "容器" as ApplicationContext { rectangle DefaultListableBeanFactory { rectangle beanDefinitionMap rectangle beanDefinitionNames } rectangle DefaultSingletonBeanRegistry { rectangle singletonObjects rectangle earlySingletonObjects rectangle singletonFactories } } rectangle "2.getBean" as getBean startProject --> configFile configFile --> DefaultListableBeanFactory:1.1将配置信息持久化为BeanDefinition DefaultListableBeanFactory --> singletonObjects:1.2遍历beanDefinitionNames,并根据BeanDefinition生成单例非懒加载bean getBean --> singletonObjects: 2.1先看单例池中是否存在 getBean --> earlySingletonObjects: 2.2再看earlySingletonObjects 是否存在 getBean --> singletonFactories: 2.3singletonFactories 是否存在 @enduml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @startuml partition 准备阶段 { :设置 PathMatchingResourcePatternResolver; :解析并设置配置文件路径; } partition 刷新容器 { :prepareRefresh:主要是验证必需属性; #Gold :obtainFreshBeanFactory:持久化配置信息,构建DefaultListableBeanFactory的beanDefinitionMap、beanDefinitionNames; :prepareBeanFactory:配置beanFactory的标准上下文特征; :postProcessBeanFactory:空实现; :invokeBeanFactoryPostProcessors:调用所有的BeanFactoryPostProcessor; :registerBeanPostProcessors: 根据类型获取到所有的BeanPostProcessor然后初始化并注册; :initMessageSource; :initApplicationEventMulticaster; :onRefresh: 空实现; :registerListeners; #Gold :finishBeanFactoryInitialization: 实例化单例非懒加载bean; } @enduml
2.时序图 3.具体流程分析 ClassPathXmlApplicationContext的构造器如下:
1 2 3 4 5 6 7 8 9 public ClassPathXmlApplicationContext (String[] configLocations, boolean refresh, ApplicationContext parent) { super (parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
3.1 设置 PathMatchingResourcePatternResolver (1)首先看父类构造器,沿着继承体系一直向上调用,直到AbstractApplicationContext:
1 2 3 4 5 6 7 public AbstractApplicationContext (ApplicationContext parent) { this (); setParent(parent); } public AbstractApplicationContext () { this .resourcePatternResolver = getResourcePatternResolver(); }
getResourcePatternResolver:
1 2 3 protected ResourcePatternResolver getResourcePatternResolver () { return new PathMatchingResourcePatternResolver (this ); }
PathMatchingResourcePatternResolver支持Ant风格的路径解析。
由于parent 为null,因此此处是将parent置空
1 2 3 4 5 6 7 8 9 10 11 12 @Override public void setParent (@Nullable ApplicationContext parent) { this .parent = parent; if (parent != null ) { Environment parentEnvironment = parent.getEnvironment(); if (parentEnvironment instanceof ConfigurableEnvironment) { getEnvironment().merge((ConfigurableEnvironment) parentEnvironment); } } }
3.2 设置配置文件路径 即AbstractRefreshableConfigApplicationContext.setConfigLocations:
1 2 3 4 5 6 7 8 9 10 11 12 public void setConfigLocations (@Nullable String... locations) { if (locations != null ) { Assert.noNullElements(locations, "Config locations must not be null" ); this .configLocations = new String [locations.length]; for (int i = 0 ; i < locations.length; i++) { this .configLocations[i] = resolvePath(locations[i]).trim(); } } else { this .configLocations = null ; } }
resolvePath:
1 2 3 protected String resolvePath (String path) { return getEnvironment().resolveRequiredPlaceholders(path); }
此方法的目的在于将占位符(placeholder)解析成实际的地址。比如可以这么写: new ClassPathXmlApplicationContext("classpath:config.xml");
那么classpath:就是需要被解析的。
getEnvironment方法来自于ConfigurableApplicationContext接口,源码很简单,如果为空就调用createEnvironment创建一个。AbstractApplicationContext.createEnvironment:
1 2 3 protected ConfigurableEnvironment createEnvironment () { return new StandardEnvironment (); }
AbstractEnvironment.resolveRequiredPlaceholders
1 2 3 4 @Override public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException { return this.propertyResolver.resolveRequiredPlaceholders(text); }
AbstractPropertyResolver.resolveRequiredPlaceholders
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Override public String resolveRequiredPlaceholders (String text) throws IllegalArgumentException { if (this .strictHelper == null ) { this .strictHelper = createPlaceholderHelper(false ); } return doResolvePlaceholders(text, this .strictHelper); } private PropertyPlaceholderHelper createPlaceholderHelper (boolean ignoreUnresolvablePlaceholders) { return new PropertyPlaceholderHelper (this .placeholderPrefix, this .placeholderSuffix, this .valueSeparator, ignoreUnresolvablePlaceholders); } private String doResolvePlaceholders (String text, PropertyPlaceholderHelper helper) { return helper.replacePlaceholders(text, this ::getPropertyAsRawString); }
这里是解析配置文件路径中包含的占位符
1 2 3 System.setProperty("spring" , "classpath" ); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ("${spring}:config.xml" );SimpleBean bean = context.getBean(SimpleBean.class);
这样就能成功设置配置文件路径了
三、refresh Spring bean解析就在此方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 @Override public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
1.prepareRefresh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 protected void prepareRefresh () { this .startupDate = System.currentTimeMillis(); this .closed.set(false ); this .active.set(true ); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this ); } else { logger.debug("Refreshing " + getDisplayName()); } } initPropertySources(); getEnvironment().validateRequiredProperties(); if (this .earlyApplicationListeners == null ) { this .earlyApplicationListeners = new LinkedHashSet <>(this .applicationListeners); } else { this .applicationListeners.clear(); this .applicationListeners.addAll(this .earlyApplicationListeners); } this .earlyApplicationEvents = new LinkedHashSet <>(); }
1.1 属性校验 AbstractEnvironment.validateRequiredProperties:
1 2 3 4 @Override public void validateRequiredProperties () throws MissingRequiredPropertiesException { this .propertyResolver.validateRequiredProperties(); }
AbstractPropertyResolver.validateRequiredProperties:
1 2 3 4 5 6 7 8 9 10 11 12 @Override public void validateRequiredProperties () { MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException (); for (String key : this .requiredProperties) { if (this .getProperty(key) == null ) { ex.addMissingRequiredProperty(key); } } if (!ex.getMissingRequiredProperties().isEmpty()) { throw ex; } }
requiredProperties是通过setRequiredProperties方法设置的,保存在一个list里面,默认是空的,也就是不需要校验任何属性。
2.obtainFreshBeanFactory 创建 BeanFactory
1 2 3 4 protected ConfigurableListableBeanFactory obtainFreshBeanFactory () { refreshBeanFactory(); return getBeanFactory(); }
调用AbstractRefreshableApplicationContext.refreshBeanFactory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Override protected final void refreshBeanFactory () throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); this .beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException ("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
2.1 定制 BeanFactory 1 2 3 4 5 6 7 8 9 10 protected void customizeBeanFactory (DefaultListableBeanFactory beanFactory) { if (this .allowBeanDefinitionOverriding != null ) { beanFactory.setAllowBeanDefinitionOverriding(this .allowBeanDefinitionOverriding); } if (this .allowCircularReferences != null ) { beanFactory.setAllowCircularReferences(this .allowCircularReferences); } }
2.2 加载Bean AbstractXmlApplicationContext.loadBeanDefinitions,这个便是核心的bean加载了:
先初始化一个 BeanDefinitionReader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Override protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader (beanFactory); beanDefinitionReader.setEnvironment(this .getEnvironment()); beanDefinitionReader.setResourceLoader(this ); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver (this )); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
2.3.1 路径解析 先获取配置文件
1 2 3 4 5 6 7 8 9 10 11 protected void loadBeanDefinitions (XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null ) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null ) { reader.loadBeanDefinitions(configLocations); } }
然后挨个加载配置文件
1 2 3 4 5 6 7 8 9 10 @Override public int loadBeanDefinitions (String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null" ); int count = 0 ; for (String location : locations) { count += loadBeanDefinitions(location); } return count; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public int loadBeanDefinitions (String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null ) { throw new BeanDefinitionStoreException ( "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available" ); } if (resourceLoader instanceof ResourcePatternResolver) { try { Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int count = loadBeanDefinitions(resources); if (actualResources != null ) { Collections.addAll(actualResources, resources); } if (logger.isTraceEnabled()) { logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]" ); } return count; } catch (IOException ex) { throw new BeanDefinitionStoreException ( "Could not resolve bean definition resource pattern [" + location + "]" , ex); } } else { Resource resource = resourceLoader.getResource(location); int count = loadBeanDefinitions(resource); if (actualResources != null ) { actualResources.add(resource); } if (logger.isTraceEnabled()) { logger.trace("Loaded " + count + " bean definitions from location [" + location + "]" ); } return count; } }
getResource的实现在AbstractApplicationContext:
1 2 3 4 5 @Override public Resource[] getResources(String locationPattern) throws IOException { return this .resourcePatternResolver.getResources(locationPattern); }
PathMatchingResourcePatternResolver是ResourceLoader继承体系的一部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @Override public Resource[] getResources(String locationPattern) throws IOException { Assert.notNull(locationPattern, "Location pattern must not be null" ); if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) { if (getPathMatcher().isPattern(locationPattern .substring(CLASSPATH_ALL_URL_PREFIX.length()))) { return findPathMatchingResources(locationPattern); } else { return findAllClassPathResources(locationPattern .substring(CLASSPATH_ALL_URL_PREFIX.length())); } } else { int prefixEnd = locationPattern.indexOf(":" ) + 1 ; if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) { return findPathMatchingResources(locationPattern); } else { return new Resource [] {getResourceLoader().getResource(locationPattern)}; } } }
isPattern:
1 2 3 4 @Override public boolean isPattern (String path) { return (path.indexOf('*' ) != -1 || path.indexOf('?' ) != -1 ); }
可以看出配置文件路径是支持ant风格的,也就是可以这么写:
1 new ClassPathXmlApplicationContext ("con*.xml" );
具体怎么解析ant风格的就不写了。
2.3.2 配置文件加载 入口方法在AbstractBeanDefinitionReader的217行:
1 2 3 4 Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int loadCount = loadBeanDefinitions(resources);
最终逐个调用XmlBeanDefinitionReader的loadBeanDefinitions方法:
1 2 3 4 @Override public int loadBeanDefinitions (Resource resource) { return loadBeanDefinitions(new EncodedResource (resource)); }
Resource是代表一种资源的接口
EncodedResource扮演的其实是一个装饰器的模式,为InputStreamSource添加了字符编码(虽然默认为null)。这样为我们自定义xml配置文件的编码方式提供了机会。
之后关键的源码只有两行:
1 2 3 4 5 public int loadBeanDefinitions (EncodedResource encodedResource) throws BeanDefinitionStoreException { InputStream inputStream = encodedResource.getResource().getInputStream(); InputSource inputSource = new InputSource (inputStream); return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); }
InputSource是org.xml.sax的类。
doLoadBeanDefinitions:
1 2 3 4 protected int doLoadBeanDefinitions (InputSource inputSource, Resource resource) { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); }
doLoadDocument:
1 2 3 4 protected Document doLoadDocument (InputSource inputSource, Resource resource) { return this .documentLoader.loadDocument(inputSource, getEntityResolver(), this .errorHandler, getValidationModeForResource(resource), isNamespaceAware()); }
documentLoader是一个DefaultDocumentLoader对象,此类是DocumentLoader接口的唯一实现。getEntityResolver方法返回ResourceEntityResolver,上面说过了。errorHandler是一个SimpleSaxErrorHandler对象。
校验模型其实就是确定xml文件使用xsd方式还是dtd方式来校验,忘了的话左转度娘。Spring会通过读取xml文件的方式判断应该采用哪种。
NamespaceAware默认false,因为默认配置了校验为true。
documentLoader是一个DefaultDocumentLoader对象,此类是DocumentLoader接口的唯一实现。getEntityResolver方法返回ResourceEntityResolver,上面说过了。errorHandler是一个SimpleSaxErrorHandler对象。
校验模型其实就是确定xml文件使用xsd方式还是dtd方式来校验,忘了的话左转度娘。Spring会通过读取xml文件的方式判断应该采用哪种。
NamespaceAware默认false,因为默认配置了校验为true。
DefaultDocumentLoader.loadDocument:
1 2 3 4 5 6 7 8 @Override public Document loadDocument (InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) { DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); return builder.parse(inputSource); }
createDocumentBuilderFactory比较有意思:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected DocumentBuilderFactory createDocumentBuilderFactory (int validationMode, boolean namespaceAware) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(namespaceAware); if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) { factory.setValidating(true ); if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) { factory.setNamespaceAware(true ); factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE); } } return factory; }
2.3.3 Bean解析 XmlBeanDefinitionReader.registerBeanDefinitions:
1 2 3 4 5 6 public int registerBeanDefinitions (Document doc, Resource resource) { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
createBeanDefinitionDocumentReader:
1 2 3 4 5 protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader () { return BeanDefinitionDocumentReader.class.cast (BeanUtils.instantiateClass(this .documentReaderClass)); }
documentReaderClass默认是DefaultBeanDefinitionDocumentReader,这其实也是策略模式,通过setter方法可以更换其实现。
注意cast方法,代替了强转。
createReaderContext:
1 2 3 4 public XmlReaderContext createReaderContext (Resource resource) { return new XmlReaderContext (resource, this .problemReporter, this .eventListener, this .sourceExtractor, this , getNamespaceHandlerResolver()); }
problemReporter是一个FailFastProblemReporter对象。
eventListener是EmptyReaderEventListener对象,此类里的方法都是空实现。
sourceExtractor是NullSourceExtractor对象,直接返回空,也是空实现。
getNamespaceHandlerResolver默认返回DefaultNamespaceHandlerResolver对象,用来获取xsd对应的处理器。
XmlReaderContext的作用感觉就是这一堆参数的容器,糅合到一起传给DocumentReader,并美其名为Context。可以看出,Spring中到处都是策略模式,大量操作被抽象成接口。
DefaultBeanDefinitionDocumentReader.registerBeanDefinitions:
1 2 3 4 5 6 @Override public void registerBeanDefinitions (Document doc, XmlReaderContext readerContext) { this .readerContext = readerContext; Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); }
doRegisterBeanDefinitions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected void doRegisterBeanDefinitions (Element root) { BeanDefinitionParserDelegate parent = this .delegate; this .delegate = createDelegate(getReaderContext(), root, parent); if (this .delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { return ; } } } preProcessXml(root); parseBeanDefinitions(root, this .delegate); postProcessXml(root); this .delegate = parent; }
delegate的作用在于处理beans标签的嵌套,其实Spring配置文件是可以写成这样的:
1 2 3 4 5 6 7 <?xml version="1.0" encoding="UTF-8" ?> <beans > <bean class ="base.SimpleBean" > </bean > <beans > <bean class ="java.lang.Object" > </bean > </beans > </beans >
xml(schema)的命名空间其实类似于java的报名,命名空间采用URL,比如Spring的是这样:
1 2 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" > </beans >
xmlns属性就是xml规范定义的用来设置命名空间的。这样设置了之后其实里面的bean元素全名就相当于http://www.springframework.org/schema/beans:bean,可以有效的防止命名冲突。命名空间可以通过规范定义的org.w3c.dom.Node.getNamespaceURI方法获得。
注意一下profile的检查, AbstractEnvironment.acceptsProfiles:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override public boolean acceptsProfiles (String... profiles) { Assert.notEmpty(profiles, "Must specify at least one profile" ); for (String profile : profiles) { if (StringUtils.hasLength(profile) && profile.charAt(0 ) == '!' ) { if (!isProfileActive(profile.substring(1 ))) { return true ; } } else if (isProfileActive(profile)) { return true ; } } return false ; }
原理很简单,注意从源码可以看出,profile属性支持!取反 。
preProcessXml方法是个空实现,供子类去覆盖,目的在于给子类一个把我们自定义的标签转为Spring标准标签的机会 , 想的真周到。
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 protected void parseBeanDefinitions (Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0 ; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
可见,对于非默认命名空间的元素交由delegate处理。
2.3默认命名空间解析 即import, alias, bean, 嵌套的beans四种元素。parseDefaultElement:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private void parseDefaultElement (Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { doRegisterBeanDefinitions(ele); } }
import 写法示例:
1 2 <import resource ="CTIContext.xml" /> <import resource ="customerContext.xml" />
importBeanDefinitionResource套路和之前的配置文件加载完全一样,不过注意被import进来的文件是先于当前文件 被解析的。
alias 加入有一个bean名为componentA-dataSource,但是另一个组件想以componentB-dataSource的名字使用,就可以这样定义:
1 <alias name ="componentA-dataSource" alias ="componentB-dataSource" />
processAliasRegistration核心源码:
1 2 3 4 5 6 protected void processAliasRegistration (Element ele) { String name = ele.getAttribute(NAME_ATTRIBUTE); String alias = ele.getAttribute(ALIAS_ATTRIBUTE); getReaderContext().getRegistry().registerAlias(name, alias); getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); }
从前面的源码可以发现,registry其实就是DefaultListableBeanFactory,它实现了BeanDefinitionRegistry接口。registerAlias方法的实现在SimpleAliasRegistry:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Override public void registerAlias (String name, String alias) { Assert.hasText(name, "'name' must not be empty" ); Assert.hasText(alias, "'alias' must not be empty" ); if (alias.equals(name)) { this .aliasMap.remove(alias); } else { String registeredName = this .aliasMap.get(alias); if (registeredName != null ) { if (registeredName.equals(name)) { return ; } if (!allowAliasOverriding()) { throw new IllegalStateException ("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'." ); } } checkForAliasCircle(name, alias); this .aliasMap.put(alias, name); } }
所以别名关系的保存使用Map完成,key为别名,value为本来的名字。
bean bean节点是Spring最最常见的节点了。
DefaultBeanDefinitionDocumentReader.processBeanDefinition:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 protected void processBeanDefinition (Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null ) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { BeanDefinitionReaderUtils.registerBeanDefinition (bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'" , ele, ex); } getReaderContext().fireComponentRegistered(new BeanComponentDefinition (bdHolder)); } }
id & name处理 最终调用BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele, BeanDefinition containingBean),源码较长,分部分说明。
首先获取到id和name属性,name属性支持配置多个,以逗号分隔,如果没有指定id,那么将以第一个name属性值代替。id必须是唯一的,name属性其实是alias的角色,可以和其它的bean重复,如果name也没有配置,那么其实什么也没做 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 String id = ele.getAttribute(ID_ATTRIBUTE);String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);List<String> aliases = new ArrayList <String>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray (nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id;if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0 ); } if (containingBean == null ) { checkNameUniqueness(beanName, aliases, ele); }
beanName生成 如果name和id属性都没有指定,那么Spring会自己生成一个, BeanDefinitionParserDelegate.parseBeanDefinitionElement:
1 2 3 beanName = this .readerContext.generateBeanName(beanDefinition); String beanClassName = beanDefinition.getBeanClassName();aliases.add(beanClassName);
可见,Spring同时会把类名作为其别名。
最终调用的是BeanDefinitionReaderUtils.generateBeanName:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public static String generateBeanName ( BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean) { String generatedBeanName = definition.getBeanClassName(); if (generatedBeanName == null ) { if (definition.getParentName() != null ) { generatedBeanName = definition.getParentName() + "$child" ; } else if (definition.getFactoryBeanName() != null ) { generatedBeanName = definition.getFactoryBeanName() + "$created" ; } } String id = generatedBeanName; if (isInnerBean) { id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition); } else { int counter = -1 ; while (counter == -1 || registry.containsBeanDefinition(id)) { counter++; id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter; } } return id; }
bean解析 还是分部分说明(parseBeanDefinitionElement)。
首先获取到bean的class属性和parent属性,配置了parent之后,当前bean会继承父bean的属性。之后根据class和parent创建BeanDefinition对象。
bean解析 还是分部分说明(parseBeanDefinitionElement)。
首先获取到bean的class属性和parent属性,配置了parent之后,当前bean会继承父bean的属性。之后根据class和parent创建BeanDefinition对象。
1 2 3 4 5 6 7 8 9 String className = null ;if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } String parent = null ;if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } AbstractBeanDefinition bd = createBeanDefinition(className, parent);
BeanDefinition的创建在BeanDefinitionReaderUtils.createBeanDefinition:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static AbstractBeanDefinition createBeanDefinition ( String parentName, String className, ClassLoader classLoader) { GenericBeanDefinition bd = new GenericBeanDefinition (); bd.setParentName(parentName); if (className != null ) { if (classLoader != null ) { bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { bd.setBeanClassName(className); } } return bd; }
之后是解析bean的其它属性,其实就是读取其配置,调用相应的setter方法保存在BeanDefinition中:
1 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
之后解析bean的decription子元素:
1 2 3 <bean id ="b" name ="one, two" class ="base.SimpleBean" > <description > SimpleBean</description > </bean >
就仅仅是个描述。
然后是meta子元素的解析,meta元素在xml配置文件里是这样的:
1 2 3 <bean id ="b" name ="one, two" class ="base.SimpleBean" > <meta key ="name" value ="skywalker" /> </bean >
注释上说,这样可以将任意的元数据附到对应的bean definition上。解析过程源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public void parseMetaElements (Element ele, BeanMetadataAttributeAccessor attributeAccessor) { NodeList nl = ele.getChildNodes(); for (int i = 0 ; i < nl.getLength(); i++) { Node node = nl.item(i); if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) { Element metaElement = (Element) node; String key = metaElement.getAttribute(KEY_ATTRIBUTE); String value = metaElement.getAttribute(VALUE_ATTRIBUTE); BeanMetadataAttribute attribute = new BeanMetadataAttribute (key, value); attribute.setSource(extractSource(metaElement)); attributeAccessor.addMetadataAttribute(attribute); } } }
AbstractBeanDefinition继承自BeanMetadataAttributeAccessor类,底层使用了一个LinkedHashMap保存metadata。这个metadata具体是做什么暂时还不知道。
lookup-method解析:
此标签的作用在于当一个bean的某个方法被设置为lookup-method后,每次调用此方法时,都会返回一个新的指定bean的对象 。用法示例:
1 2 3 4 5 <bean id ="apple" class ="cn.com.willchen.test.di.Apple" scope ="prototype" /> <bean id ="fruitPlate" class ="cn.com.willchen.test.di.FruitPlate" > <lookup-method name ="getFruit" bean ="apple" /> </bean >
数据保存在Set中,对应的类是MethodOverrides。可以参考:
Spring - lookup-method方式实现依赖注入
replace-mothod解析:
此标签用于替换bean里面的特定的方法实现,替换者必须实现Spring的MethodReplacer接口,有点像aop的意思。
配置文件示例:
1 2 3 4 5 6 <bean name ="replacer" class ="springroad.deomo.chap4.MethodReplace" /> <bean name ="testBean" class ="springroad.deomo.chap4.LookupMethodBean" > <replaced-method name ="test" replacer ="replacer" > <arg-type match ="String" /> </replaced-method > </bean >
arg-type的作用是指定替换方法的参数类型,因为接口的定义参数都是Object的。参考: SPRING.NET 1.3.2 学习20–方法注入之替换方法注入
解析之后将数据放在ReplaceOverride对象中,里面有一个LinkedList专门用于保存arg-type。
构造参数(constructor-arg)解析:
作用一目了然,使用示例:
1 2 3 4 5 <bean class ="base.SimpleBean" > <constructor-arg > <value type ="java.lang.String" > Cat</value > </constructor-arg > </bean >
type一般不需要指定,除了泛型集合那种。除此之外,constructor-arg还支持name, index, ref等属性,可以具体的指定参数的位置等。构造参数解析后保存在BeanDefinition内部一个ConstructorArgumentValues对象中。如果设置了index属性,那么以Map<Integer, ValueHolder>的形式保存,反之,以List的形式保存。
property解析:
非常常用的标签,用以为bean的属性赋值,支持value和ref两种形式,示例:
1 2 3 <bean class ="base.SimpleBean" > <property name ="name" value ="skywalker" /> </bean >
value和ref属性不能同时出现,如果是ref,那么将其值保存在不可变的RuntimeBeanReference对象中,其实现了BeanReference接口,此接口只有一个getBeanName方法。如果是value,那么将其值保存在TypedStringValue对象中。最终将对象保存在BeanDefinition内部一个MutablePropertyValues对象中(内部以ArrayList实现)。
qualifier解析:
配置示例:
1 2 3 4 5 6 7 8 9 10 11 <bean class ="base.Student" > <property name ="name" value ="skywalker" > </property > <property name ="age" value ="12" > </property > <qualifier type ="org.springframework.beans.factory.annotation.Qualifier" value ="student" /> </bean > <bean class ="base.Student" > <property name ="name" value ="seaswalker" > </property > <property name ="age" value ="15" > </property > <qualifier value ="student_2" > </qualifier > </bean > <bean class ="base.SimpleBean" />
SimpleBean部分源码:
1 2 3 @Autowired @Qualifier("student") private Student student;
此标签和@Qualifier, @Autowired两个注解一起使用才有作用。@Autowired注解采用按类型查找的方式进行注入,如果找到多个需要类型的bean便会报错,有了@Qualifier标签就可以再按照此注解指定的名称查找。两者结合相当于实现了按类型+名称注入。type属性可以不指定,因为默认就是那个。qualifier标签可以有attribute子元素,比如:
1 2 3 <qualifier type ="org.springframework.beans.factory.annotation.Qualifier" value ="student" > <attribute key ="id" value ="1" /> </qualifier >
貌似是用来在qualifier也区分不开的时候使用。attribute键值对保存在BeanMetadataAttribute对象中。整个qualifier保存在AutowireCandidateQualifier对象中。
Bean装饰 这部分是针对其它schema的属性以及子节点,比如:
1 2 3 <bean class ="base.Student" primary ="true" > <context:property-override /> </bean >
没见过这种用法,留个坑。
Bean注册 BeanDefinitionReaderUtils.registerBeanDefinition:
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void registerBeanDefinition ( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) { String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); String[] aliases = definitionHolder.getAliases(); if (aliases != null ) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }
registry其实就是DefaultListableBeanFactory对象,registerBeanDefinition方法主要就干了这么两件事:
1 2 3 4 5 @Override public void registerBeanDefinition (String beanName, BeanDefinition beanDefinition) { this .beanDefinitionMap.put(beanName, beanDefinition); this .beanDefinitionNames.add(beanName); }
一个是Map,另一个是List,一目了然。registerAlias方法的实现在其父类SimpleAliasRegistry,就是把键值对放在了一个ConcurrentHashMap里。
ComponentRegistered事件触发:
默认是个空实现,前面说过了。
BeanDefiniton数据结构 BeanDefiniton数据结构如下图:
beans beans元素的嵌套直接递归调用DefaultBeanDefinitionDocumentReader.parseBeanDefinitions。
其它命名空间解析 入口在DefaultBeanDefinitionDocumentReader.parseBeanDefinitions->BeanDefinitionParserDelegate.parseCustomElement(第二个参数为空):
1 2 3 4 5 public BeanDefinition parseCustomElement (Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); NamespaceHandler handler = this .readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); return handler.parse(ele, new ParserContext (this .readerContext, this , containingBd)); }
NamespaceHandlerResolver由XmlBeanDefinitionReader初始化,是一个DefaultNamespaceHandlerResolver对象,也是NamespaceHandlerResolver接口的唯一实现。
其resolve方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override public NamespaceHandler resolve (String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null ) { return null ; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; Class<?> handlerClass = ClassUtils.forName(className, this .classLoader); NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } }
容易看出,Spring其实使用了一个Map了保存其映射关系,key就是命名空间的uri,value是NamespaceHandler对象或是Class完整名,如果发现是类名,那么用反射的方法进行初始化,如果是NamespaceHandler对象,那么直接返回 。
NamespaceHandler映射关系来自于各个Spring jar包下的META-INF/spring.handlers文件,以spring-context包为例:
1 2 3 4 5 http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
NamespaceHandler继承体系
init resolve中调用了其init方法,此方法用以向NamespaceHandler对象注册BeanDefinitionParser对象。**此接口用以解析顶层(beans下)的非默认命名空间元素,比如<context:annotation-config />
**。
所以这样逻辑就很容易理解了: 每种子标签的解析仍是策略模式的体现,init负责向父类NamespaceHandlerSupport注册不同的策略,由父类的NamespaceHandlerSupport.parse方法根据具体的子标签调用相应的策略完成解析的过程 。
此部分较为重要,所以重新开始大纲。
BeanFactory数据结构 BeanDefinition在BeanFactory中的主要数据结构如下图:
prepareBeanFactory 此方法负责对BeanFactory进行一些特征的设置工作,”特征”包含这么几个方面:
BeanExpressionResolver 此接口只有一个实现: StandardBeanExpressionResolver。接口只含有一个方法:
1 Object evaluate (String value, BeanExpressionContext evalContext)
prepareBeanFactory将一个此对象放入BeanFactory:
1 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver (beanFactory.getBeanClassLoader()));
StandardBeanExpressionResolver对象内部有一个关键的成员: SpelExpressionParser,其整个类图:
这便是Spring3.0开始出现的Spel表达式的解释器。
PropertyEditorRegistrar 此接口用于向Spring注册java.beans.PropertyEditor,只有一个方法:
1 registerCustomEditors(PropertyEditorRegistry registry)
实现也只有一个: ResourceEditorRegistrar。
在编写xml配置时,我们设置的值都是字符串形式,所以在使用时肯定需要转为我们需要的类型,PropertyEditor接口正是定义了这么个东西。
prepareBeanFactory:
1 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar (this , getEnvironment()));
BeanFactory也暴露了registerCustomEditors方法用以添加自定义的转换器,所以这个地方是组合模式的体现。
我们有两种方式可以添加自定义PropertyEditor:
参考: 深入理解JavaBean(2):属性编辑器PropertyEditor
环境注入 在Spring中我们自己的bean可以通过实现EnvironmentAware等一系列Aware接口获取到Spring内部的一些对象。prepareBeanFactory:
1 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor (this ));
ApplicationContextAwareProcessor核心的invokeAwareInterfaces方法:
1 2 3 4 5 6 7 8 9 10 11 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); } } }
依赖解析忽略 此部分设置哪些接口在进行依赖注入的时候应该被忽略:
1 2 3 4 5 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
bean伪装 有些对象并不在BeanFactory中,但是我们依然想让它们可以被装配,这就需要伪装一下:
1 2 3 4 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this ); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this ); beanFactory.registerResolvableDependency(ApplicationContext.class, this );
伪装关系保存在一个Map<Class<?>, Object>里。
LoadTimeWeaver 如果配置了此bean,那么:
1 2 3 4 5 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor (beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader (beanFactory.getBeanClassLoader())); }
这个东西具体是干什么的在后面context:load-time-weaver中说明。
注册环境 源码:
1 2 3 4 5 6 7 8 9 10 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()); }
containsLocalBean特殊之处在于不会去父BeanFactory寻找。
postProcessBeanFactory 此方法允许子类在所有的bean尚未初始化之前注册BeanPostProcessor。空实现且没有子类覆盖。
invokeBeanFactoryPostProcessors BeanFactoryPostProcessor接口允许我们在bean正是初始化之前改变其值。此接口只有一个方法:
1 void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) ;
有两种方式可以向Spring添加此对象:
通过代码的方式:
1 context.addBeanFactoryPostProcessor
通过xml配置的方式:
1 <bean class ="base.SimpleBeanFactoryPostProcessor" />
注意此时尚未进行bean的初始化工作,初始化是在后面的finishBeanFactoryInitialization进行的,所以在BeanFactoryPostProcessor对象中获取bean会导致提前初始化。
此方法的关键源码:
1 2 3 4 protected void invokeBeanFactoryPostProcessors (ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); }
getBeanFactoryPostProcessors获取的就是AbstractApplicationContext的成员beanFactoryPostProcessors(ArrayList),但是很有意思,只有通过context.addBeanFactoryPostProcessor这种方式添加的才会出现在这个List里,所以对于xml配置方式,此List其实没有任何元素。玄机就在PostProcessorRegistrationDelegate里 。
核心思想就是使用BeanFactory的getBeanNamesForType方法获取相应的BeanDefinition的name数组,之后逐一调用getBean方法获取到bean(初始化),getBean方法后面再说。
注意此处有一个优先级的概念,如果你的BeanFactoryPostProcessor同时实现了Ordered或者是PriorityOrdered接口,那么会被首先执行。
BeanPostProcessor注册 此部分实质上是在BeanDefinitions中寻找BeanPostProcessor,之后调用BeanFactory.addBeanPostProcessor方法保存在一个List中,注意添加时仍然有优先级的概念,优先级高的在前面。
MessageSource 此接口用以支持Spring国际化。继承体系如下:
AbstractApplicationContext的initMessageSource()方法就是在BeanFactory中查找MessageSource的bean,如果配置了此bean,那么调用getBean方法完成其初始化并将其保存在AbstractApplicationContext内部messageSource成员变量中,用以处理ApplicationContext的getMessage调用,因为从继承体系上来看,ApplicationContext是MessageSource的子类,此处是委托模式的体现。如果没有配置此bean,那么初始化一个DelegatingMessageSource对象,此类是一个空实现,同样用以处理getMessage调用请求。
参考: 学习Spring必学的Java基础知识(8)—-国际化信息
事件驱动 此接口代表了Spring的事件驱动(监听器)模式。一个事件驱动包含三部分:
事件 java的所有事件对象一般都是java.util.EventObject的子类,Spring的整个继承体系如下:
发布者 ApplicationEventPublisher
一目了然。
ApplicationEventMulticaster ApplicationEventPublisher实际上正是将请求委托给ApplicationEventMulticaster来实现的。其继承体系:
监听器 所有的监听器是jdk EventListener的子类,这是一个mark接口。继承体系:
可以看出SmartApplicationListener和GenericApplicationListener是高度相似的,都提供了事件类型检测和顺序机制,而后者是从Spring4.2加入的,Spring官方文档推荐使用后者代替前者。
初始化 前面说过ApplicationEventPublisher是通过委托给ApplicationEventMulticaster实现的,所以refresh方法中完成的是对ApplicationEventMulticaster的初始化:
1 2 initApplicationEventMulticaster();
initApplicationEventMulticaster则首先在BeanFactory中寻找ApplicationEventMulticaster的bean,如果找到,那么调用getBean方法将其初始化,如果找不到那么使用SimpleApplicationEventMulticaster。
事件发布 AbstractApplicationContext.publishEvent核心代码:
1 2 3 protected void publishEvent (Object event, ResolvableType eventType) { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); }
SimpleApplicationEventMulticaster.multicastEvent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override public void multicastEvent (final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null ) { executor.execute(new Runnable () { @Override public void run () { invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }
监听器获取 获取当然还是通过beanFactory的getBean来完成的,值得注意的是Spring在此处使用了缓存(ConcurrentHashMap)来加速查找的过程。
同步/异步 可以看出,如果executor不为空,那么监听器的执行实际上是异步的。那么如何配置同步/异步呢?
全局 1 2 3 4 <task:executor id ="multicasterExecutor" pool-size ="3" /> <bean class ="org.springframework.context.event.SimpleApplicationEventMulticaster" > <property name ="taskExecutor" ref ="multicasterExecutor" > </property > </bean >
task schema是Spring从3.0开始加入的,使我们可以不再依赖于Quartz实现定时任务,源码在org.springframework.core.task包下,使用需要引入schema:
1 2 xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"
可以参考: Spring定时任务的几种实现
注解 开启注解支持:
1 2 3 4 5 6 7 8 <aop:aspectj-autoproxy proxy-target-class ="true" /> <task:scheduler id ="scheduler" pool-size ="10" /> <task:executor id ="executor" pool-size ="10" /> <task:annotation-driven executor ="executor" scheduler ="scheduler" proxy-target-class ="true" />
在代码中使用示例:
1 2 3 4 5 6 7 8 @Component public class EmailRegisterListener implements ApplicationListener <RegisterEvent> { @Async @Override public void onApplicationEvent (final RegisterEvent event) { System.out.println("注册成功,发送确认邮件给:" + ((User)event.getSource()).getUsername()); } }
参考: 详解Spring事件驱动模型
onRefresh 这又是一个模版方法,允许子类在进行bean初始化之前进行一些定制操作。默认空实现。
ApplicationListener注册 registerListeners方法干的,没什么好说的。
singleton初始化 finishBeanFactoryInitialization:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 protected void finishBeanFactoryInitialization (ConfigurableListableBeanFactory beanFactory) { if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver () { @Override public String resolveStringValue (String strVal) { return getEnvironment().resolvePlaceholders(strVal); } }); } String[] weaverAwareNames = beanFactory.getBeanNamesForType (LoadTimeWeaverAware.class, false , false ); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } beanFactory.freezeConfiguration(); beanFactory.preInstantiateSingletons(); }
分部分说明。
ConversionService 此接口用于类型之间的转换,在Spring里其实就是把配置文件中的String转为其它类型,从3.0开始出现,目的和jdk的PropertyEditor接口是一样的,参考ConfigurableBeanFactory.setConversionService注释:
Specify a Spring 3.0 ConversionService to use for converting property values, as an alternative to JavaBeans PropertyEditors. @since 3.0
StringValueResolver 用于解析注解的值。接口只定义了一个方法:
1 String resolveStringValue (String strVal) ;
LoadTimeWeaverAware 实现了此接口的bean可以得到LoadTimeWeaver,此处仅仅初始化。
初始化 DefaultListableBeanFactory.preInstantiateSingletons:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @Override public void preInstantiateSingletons () throws BeansException { List<String> beanNames = new ArrayList <String>(this .beanDefinitionNames); for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction <Boolean>() { @Override public Boolean run () { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null ) { AccessController.doPrivileged(new PrivilegedAction <Object>() { @Override public Object run () { smartSingleton.afterSingletonsInstantiated(); return null ; } }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
首先进行Singleton的初始化,其中如果bean是FactoryBean类型(注意,只定义了factory-method属性的普通bean并不是FactoryBean),并且还是SmartFactoryBean类型,那么需要判断是否需要eagerInit(isEagerInit是此接口定义的方法)。
getBean 这里便是bean初始化的核心逻辑。源码比较复杂,分开说。以getBean(String name)为例。AbstractBeanFactory.getBean:
1 2 3 4 @Override public Object getBean (String name) throws BeansException { return doGetBean(name, null , null , false ); }
第二个参数表示bean的Class类型,第三个表示创建bean需要的参数,最后一个表示不需要进行类型检查。
beanName转化 1 final String beanName = transformedBeanName(name);
这里是将FactoryBean的前缀去掉以及将别名转为真实的名字。
手动注册bean检测 Spring其实手动注册了一些单例bean。这一步就是检测是不是这些bean。如果是,那么再检测是不是工厂bean,如果是返回其工厂方法返回的实例,如果不是返回bean本身。
1 2 3 4 Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null ) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); }
检查父容器 如果父容器存在并且存在此bean定义,那么交由其父容器初始化:
1 2 3 4 5 6 7 8 9 10 11 12 13 BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null ) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } }
依赖初始化 bean可以由depends-on属性配置依赖的bean。Spring会首先初始化依赖的bean。
1 2 3 4 5 6 7 8 9 10 11 12 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null ) { for (String dependsOnBean : dependsOn) { if (isDependent(beanName, dependsOnBean)) { throw new BeanCreationException (mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'" ); } registerDependentBean(dependsOnBean, beanName); getBean(dependsOnBean); } }
registerDependentBean进行了依赖关系的注册,这么做的原因是Spring在即进行bean销毁的时候会首先销毁被依赖的bean。依赖关系的保存是通过一个ConcurrentHashMap<String, Set>完成的,key是bean的真实名字。
Singleton初始化 虽然这里大纲是Singleton初始化,但是getBean方法本身是包括所有scope的初始化,在这里一次说明了。
1 2 3 4 5 6 7 8 9 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory <Object>() { @Override public Object getObject () throws BeansException { return createBean(beanName, mbd, args); } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
getSingleton方法 是否存在 首先会检测是否已经存在,如果存在,直接返回:
1 2 3 synchronized (this .singletonObjects) { Object singletonObject = this .singletonObjects.get(beanName); }
所有的单例bean都保存在这样的数据结构中: ConcurrentHashMap<String, Object>
。
bean创建 源码位于AbstractAutowireCapableBeanFactory.createBean,主要分为几个部分:
lookup-method检测 此部分用于检测lookup-method标签配置的方法是否存在:
1 2 RootBeanDefinition mbdToUse = mbd;mbdToUse.prepareMethodOverrides();
prepareMethodOverrides:
1 2 3 4 5 6 7 8 9 10 11 12 public void prepareMethodOverrides () throws BeanDefinitionValidationException { MethodOverrides methodOverrides = getMethodOverrides(); if (!methodOverrides.isEmpty()) { Set<MethodOverride> overrides = methodOverrides.getOverrides(); synchronized (overrides) { for (MethodOverride mo : overrides) { prepareMethodOverride(mo); } } } }
prepareMethodOverride:
1 2 3 4 5 6 7 8 9 10 11 protected void prepareMethodOverride (MethodOverride mo) { int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); if (count == 0 ) { throw new BeanDefinitionValidationException ( "Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]" ); } else if (count == 1 ) { mo.setOverloaded(false ); } }
InstantiationAwareBeanPostProcessor触发 在这里触发的是其postProcessBeforeInitialization和postProcessAfterInstantiation方法。
1 2 3 4 5 6 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null ) { return bean; } Object beanInstance = doCreateBean(beanName, mbdToUse, args);return beanInstance;
继续:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 protected Object resolveBeforeInstantiation (String beanName, RootBeanDefinition mbd) { Object bean = null ; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null ) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null ) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null ); } return bean; }
从这里可以看出,如果InstantiationAwareBeanPostProcessor返回的不是空,那么将不会继续执行剩下的Spring初始化流程,此接口用于初始化自定义的bean,主要是在Spring内部使用 。
doCreateBean 同样分为几部分。
创建(createBeanInstance) 关键代码:
1 2 3 4 BeanWrapper instanceWrapper = null ;if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); }
createBeanInstance的创建过程又分为以下几种情况:
工厂bean:
调用instantiateUsingFactoryMethod方法:
1 2 3 4 protected BeanWrapper instantiateUsingFactoryMethod ( String beanName, RootBeanDefinition mbd, Object[] explicitArgs) { return new ConstructorResolver (this ).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }
注意,此处的工厂bean指的是配置了factory-bean/factory-method属性的bean,不是实现了FacrotyBean接口的bean。如果没有配置factory-bean属性,那么factory-method指向的方法必须是静态的。此方法主要做了这么几件事:
初始化一个BeanWrapperImpl对象。
根据设置的参数列表使用反射的方法寻找相应的方法对象。
InstantiationStrategy:
bean的初始化在此处又抽成了策略模式,类图:
instantiateUsingFactoryMethod部分源码:
1 2 beanInstance = this .beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this .beanFactory, factoryBean, factoryMethodToUse, argsToUse);
getInstantiationStrategy返回的是CglibSubclassingInstantiationStrategy对象。此处instantiate实现也很简单,就是调用工厂方法的Method对象反射调用其invoke即可得到对象,SimpleInstantiationStrategy.
instantiate核心源码:
1 2 3 4 5 @Override public Object instantiate (RootBeanDefinition bd, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, Object... args) { return factoryMethod.invoke(factoryBean, args); }
构造器自动装配
createBeanInstance部分源码:
1 2 3 4 5 6 7 8 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); }
determineConstructorsFromBeanPostProcessors源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName) { if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); if (ctors != null ) { return ctors; } } } } return null ; }
可见是由SmartInstantiationAwareBeanPostProcessor决定的,默认是没有配置这种东西的。
之后就是判断bean的自动装配模式,可以通过如下方式配置:
1 <bean id ="student" class ="base.Student" primary ="true" autowire ="default" />
autowire共有以下几种选项:
no: 默认的,不进行自动装配。在这种情况下,只能通过ref方式引用其它bean。
byName: 根据bean里面属性的名字在BeanFactory中进行查找并装配。
byType: 按类型。
constructor: 以byType的方式查找bean的构造参数列表。
default: 由父bean决定。
参考: Spring - bean的autowire属性(自动装配)
autowireConstructor调用的是ConstructorResolver.autowireConstructor,此方法主要做了两件事:
最终调用的还是CglibSubclassingInstantiationStrategy.instantiate方法,关键源码:
1 2 3 4 5 6 7 8 9 10 @Override public Object instantiate (RootBeanDefinition bd, String beanName, BeanFactory owner, final Constructor<?> ctor, Object... args) { if (bd.getMethodOverrides().isEmpty()) { return BeanUtils.instantiateClass(ctor, args); } else { return instantiateWithMethodInjection(bd, beanName, owner, ctor, args); } }
可以看出,如果配置了lookup-method标签,得到的实际上是用Cglib生成的目标类的代理子类 。
CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection:
1 2 3 4 5 @Override protected Object instantiateWithMethodInjection (RootBeanDefinition bd, String beanName, BeanFactory owner,Constructor<?> ctor, Object... args) { return new CglibSubclassCreator (bd, owner).instantiate(ctor, args); }
默认构造器
一行代码,很简单:
1 2 return instantiateBean(beanName, mbd);
MergedBeanDefinitionPostProcessor 触发源码:
1 2 3 4 5 6 synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true ; } }
此接口也是Spring内部使用的,不管它了。
属性解析 入口方法: AbstractAutowireCapableBeanFactory.populateBean,它的作用是: 根据autowire类型进行autowire by name,by type 或者是直接进行设置,简略后的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 protected void populateBean (String beanName, RootBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues (pvs); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } applyPropertyValues(beanName, mbd, bw, pvs); }
autowireByName源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 protected void autowireByName ( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { Object bean = getBean(propertyName); pvs.add(propertyName, bean); registerDependentBean(propertyName, beanName); } } }
autowireByType也是同样的套路,所以可以得出结论: autowireByName和autowireByType方法只是先获取到引用的bean,真正的设值是在applyPropertyValues中进行的。
属性设置 Spring判断一个属性可不可以被设置(存不存在)是通过java bean的内省操作来完成的,也就是说,属性可以被设置的条件是此属性拥有public的setter方法,并且注入时的属性名应该是setter的名字 。
初始化 此处的初始化指的是bean已经构造完成,执行诸如调用其init方法的操作。相关源码:
1 2 3 4 5 6 7 8 Object exposedObject = bean;try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null ) { exposedObject = initializeBean(beanName, exposedObject, mbd); } }
initializeBean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 protected Object initializeBean (final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null ) { AccessController.doPrivileged(new PrivilegedAction <Object>() { @Override public Object run () { invokeAwareMethods(beanName, bean); return null ; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } invokeInitMethods(beanName, wrappedBean, mbd); if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
主要的操作步骤一目了然。
Aware方法触发:
我们的bean有可能实现了一些XXXAware接口,此处就是负责调用它们:
1 2 3 4 5 6 7 8 9 10 11 12 13 private void invokeAwareMethods (final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this ); } } }
BeanPostProcessor触发,没什么好说的
调用init方法:
在XML配置中,bean可以有一个init-method属性来指定初始化时调用的方法。从原理来说,其实就是一个反射调用。不过注意这里有一个InitializingBean的概念。
此接口只有一个方法:
1 void afterPropertiesSet () throws Exception;
如果我们的bean实现了此接口,那么此方法会首先被调用。此接口的意义在于: 当此bean的所有属性都被设置(注入)后,给bean一个利用现有属性重新组织或是检查属性的机会。感觉和init方法有些冲突,不过此接口在Spring被广泛使用。
getObjectForBeanInstance 位于AbstractBeanFactory,此方法的目的在于如果bean是FactoryBean,那么返回其工厂方法创建的bean,而不是自身。
Prototype初始化 AbstractBeanFactory.doGetBean相关源码:
1 2 3 4 5 6 7 8 9 10 11 12 else if (mbd.isPrototype()) { Object prototypeInstance = null ; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
beforePrototypeCreation 此方法用于确保在同一时刻只能有一个此bean在初始化。
createBean 和单例的是一样的,不在赘述。
afterPrototypeCreation 和beforePrototypeCreation对应的,你懂的。
总结 可以看出,初始化其实和单例是一样的,只不过单例多了一个是否已经存在的检查。
其它Scope初始化 其它就指的是request、session。此部分源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 else { String scopeName = mbd.getScope(); final Scope scope = this .scopes.get(scopeName); if (scope == null ) { throw new IllegalStateException ("No Scope registered for scope name '" + scopeName + "'" ); } Object scopedInstance = scope.get(beanName, new ObjectFactory <Object>() { @Override public Object getObject () throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); }
scopes是一个LinkedHashMap<String, Scope>,可以调用 ConfigurableBeanFactory定义的registerScope方法注册其值。
Scope接口继承体系:
根据socpe.get的注释,此方法如果找到了叫做beanName的bean,那么返回,如果没有,将调用ObjectFactory创建之。Scope的实现参考类图。
四、循环依赖
spring源码系列(一)——spring循环引用
1 2 3 4 5 6 7 singletonsCurrentlyInCreation AbstractBeanFactory.doGetBean -> DefaultSingletonBeanRegistry.getSingleton -> DefaultSingletonBeanRegistry.beforeSingletonCreation -> AbstractAutowireCapableBeanFactory.doCreateBean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // AbstractBeanFactory protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 尝试通过bean名称获取目标bean对象,比如这里的A对象 Object sharedInstance = getSingleton(beanName); // 我们这里的目标对象都是单例的 // Create bean instance. if (mbd.isSingleton()) { // 这里就尝试创建目标对象,第二个参数传的就是一个ObjectFactory类型的对象,这里是使用Java8的lamada // 表达式书写的,只要上面的getSingleton()方法返回值为空,则会调用这里的getSingleton()方法来创建 // 目标对象 sharedInstance = getSingleton(beanName, () -> { try { // 尝试创建目标对象 return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); } return (T) bean; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public Object getSingleton (String beanName, ObjectFactory<?> singletonFactory) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null ) { beforeSingletonCreation(beanName); singletonObject = singletonFactory.getObject(); afterSingletonCreation(beanName); addSingleton(beanName, singletonObject); } } @Nullable protected Object getSingleton (String beanName, boolean allowEarlyReference) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this .singletonObjects) { singletonObject = this .earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this .singletonFactories.get(beanName); if (singletonFactory != null ) { singletonObject = singletonFactory.getObject(); this .earlySingletonObjects.put(beanName, singletonObject); this .singletonFactories.remove(beanName); } } } } return singletonObject; }
五、设计模式 策略模式
模板方法模式
单例模式
代理模式
观察者模式(事件发布与监听)
适配器模式(spring MVC)