Spring源代码分析(7)---XmlBeanFactory(迟来的正主)
2008-09-22 21:29
459 查看
前面几小节,我们一直都在分析spring的一些基本类,这一节我们来看看XmlBeanFactory这个正主,ioc工厂;
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
从reader.loadBeanDefinitions(resource);可见,从外部加载xml配置文件,XmlBeanFactory是通过委托给XmlBeanDefinitionReader做的,其他都是DefaultListableBeanFactory 继承而来;
那么,我们重点来分析一些xml文件是如何把配置加载到BeanFactory中的:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {
XmlBeanDefinitionParser parser =
(XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);
return parser.registerBeanDefinitions(this, doc, resource);
}
registerBeanDefinitions是reader是通过SAXBuilder把外部xml转换成为了Document,然后用BeanDefinition解析器来解析这个documeng文档;
public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource)
throws BeanDefinitionStoreException {
this.beanDefinitionReader = reader;
this.resource = resource;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
initDefaults(root);
if (logger.isDebugEnabled()) {
logger.debug("Default lazy init '" + getDefaultLazyInit() + "'");
logger.debug("Default autowire '" + getDefaultAutowire() + "'");
logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'");
}
preProcessXml(root);
int beanDefinitionCount = parseBeanDefinitions(root);
if (logger.isDebugEnabled()) {
logger.debug("Found " + beanDefinitionCount + " <bean> elements in " + resource);
}
postProcessXml(root);
return beanDefinitionCount;
}
registerBeanDefinitions方法从root元素开始处理整个document,在这里我们可以在一次看见spring给我们留出来的钩子方法,典型的模板方法的应用;
preProcessXml(root){};
postProcessXml(root){};
protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {
NodeList nl = root.getChildNodes();
int beanDefinitionCount = 0;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (IMPORT_ELEMENT.equals(node.getNodeName())) {
importBeanDefinitionResource(ele);
}
else if (ALIAS_ELEMENT.equals(node.getNodeName())) {
String name = ele.getAttribute(NAME_ATTRIBUTE);
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias);
}
else if (BEAN_ELEMENT.equals(node.getNodeName())) {
beanDefinitionCount++;
BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory());
}
}
}
return beanDefinitionCount;
}
parseBeanDefinitions方法中,我们开始遍历整个文档的节点,处理每个节点;并且从节点的名字,我们可以判断出三种节点,一种是<import>一种是<alias>一种是<bean>
BeanDefinitionHolder 是一个含有BeanDefinition和Bean name的存储器,我们主要来看一下spring如何从bean element 构造出BeanDefinition();
protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele, boolean isInnerBean)
throws BeanDefinitionStoreException {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = (String) aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);
if (!StringUtils.hasText(beanName) && beanDefinition instanceof AbstractBeanDefinition) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
(AbstractBeanDefinition) beanDefinition, this.beanDefinitionReader.getBeanFactory(), isInnerBean);
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
主要是获取alias,把名字用.;分开,解析成为别名;
protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName)
throws BeanDefinitionStoreException {
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);
}
try {
ConstructorArgumentValues cargs = parseConstructorArgElements(ele, beanName);
MutablePropertyValues pvs = parsePropertyElements(ele, beanName);
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
className, parent, cargs, pvs, getBeanDefinitionReader().getBeanClassLoader());
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));
}
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
if (DEFAULT_VALUE.equals(dependencyCheck)) {
dependencyCheck = getDefaultDependencyCheck();
}
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
if (DEFAULT_VALUE.equals(autowire)) {
autowire = getDefaultAutowire();
}
bd.setAutowireMode(getAutowireMode(autowire));
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!"".equals(initMethodName)) {
bd.setInitMethodName(initMethodName);
}
}
else {
if (getDefaultInitMethod() != null) {
bd.setInitMethodName(getDefaultInitMethod());
bd.setEnforceInitMethod(false);
}
}
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
if (!"".equals(destroyMethodName)) {
bd.setDestroyMethodName(destroyMethodName);
}
}
else {
if (getDefaultDestroyMethod() != null) {
bd.setDestroyMethodName(getDefaultDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
}
parseLookupOverrideSubElements(ele, beanName, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, beanName, bd.getMethodOverrides());
bd.setResourceDescription(getResource().getDescription());
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
}
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
// Just apply default to singletons, as lazy-init has no meaning for prototypes.
lazyInit = getDefaultLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
return bd;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (ClassNotFoundException ex) {
throw new BeanDefinitionStoreException(
getResource(), beanName, "Bean class [" + className + "] not found", ex);
}
catch (NoClassDefFoundError err) {
throw new BeanDefinitionStoreException(
getResource(), beanName, "Class that bean class [" + className + "] depends on not found", err);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
getResource(), beanName, "Unexpected failure during bean definition parsing", ex);
}
}
上述代码详细的解析了各种元素,并且把他set到BeanDefinition中去;
最后:public static void registerBeanDefinition(
BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeanDefinitionStoreException {
// Register bean definition under primary name.
beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());
// Register aliases for bean name, if any.
if (bdHolder.getAliases() != null) {
for (int i = 0; i < bdHolder.getAliases().length; i++) {
beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);
}
}
}
很荣幸的,该BeanDefinition被加载到该BeanFactory的beanDefinitions的map中,被用来在getBean()中转换为Bean;
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
从reader.loadBeanDefinitions(resource);可见,从外部加载xml配置文件,XmlBeanFactory是通过委托给XmlBeanDefinitionReader做的,其他都是DefaultListableBeanFactory 继承而来;
那么,我们重点来分析一些xml文件是如何把配置加载到BeanFactory中的:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {
XmlBeanDefinitionParser parser =
(XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);
return parser.registerBeanDefinitions(this, doc, resource);
}
registerBeanDefinitions是reader是通过SAXBuilder把外部xml转换成为了Document,然后用BeanDefinition解析器来解析这个documeng文档;
public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource)
throws BeanDefinitionStoreException {
this.beanDefinitionReader = reader;
this.resource = resource;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
initDefaults(root);
if (logger.isDebugEnabled()) {
logger.debug("Default lazy init '" + getDefaultLazyInit() + "'");
logger.debug("Default autowire '" + getDefaultAutowire() + "'");
logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'");
}
preProcessXml(root);
int beanDefinitionCount = parseBeanDefinitions(root);
if (logger.isDebugEnabled()) {
logger.debug("Found " + beanDefinitionCount + " <bean> elements in " + resource);
}
postProcessXml(root);
return beanDefinitionCount;
}
registerBeanDefinitions方法从root元素开始处理整个document,在这里我们可以在一次看见spring给我们留出来的钩子方法,典型的模板方法的应用;
preProcessXml(root){};
postProcessXml(root){};
protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {
NodeList nl = root.getChildNodes();
int beanDefinitionCount = 0;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (IMPORT_ELEMENT.equals(node.getNodeName())) {
importBeanDefinitionResource(ele);
}
else if (ALIAS_ELEMENT.equals(node.getNodeName())) {
String name = ele.getAttribute(NAME_ATTRIBUTE);
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias);
}
else if (BEAN_ELEMENT.equals(node.getNodeName())) {
beanDefinitionCount++;
BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory());
}
}
}
return beanDefinitionCount;
}
parseBeanDefinitions方法中,我们开始遍历整个文档的节点,处理每个节点;并且从节点的名字,我们可以判断出三种节点,一种是<import>一种是<alias>一种是<bean>
BeanDefinitionHolder 是一个含有BeanDefinition和Bean name的存储器,我们主要来看一下spring如何从bean element 构造出BeanDefinition();
protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele, boolean isInnerBean)
throws BeanDefinitionStoreException {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = (String) aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);
if (!StringUtils.hasText(beanName) && beanDefinition instanceof AbstractBeanDefinition) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
(AbstractBeanDefinition) beanDefinition, this.beanDefinitionReader.getBeanFactory(), isInnerBean);
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
主要是获取alias,把名字用.;分开,解析成为别名;
protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName)
throws BeanDefinitionStoreException {
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);
}
try {
ConstructorArgumentValues cargs = parseConstructorArgElements(ele, beanName);
MutablePropertyValues pvs = parsePropertyElements(ele, beanName);
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
className, parent, cargs, pvs, getBeanDefinitionReader().getBeanClassLoader());
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));
}
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
if (DEFAULT_VALUE.equals(dependencyCheck)) {
dependencyCheck = getDefaultDependencyCheck();
}
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
if (DEFAULT_VALUE.equals(autowire)) {
autowire = getDefaultAutowire();
}
bd.setAutowireMode(getAutowireMode(autowire));
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!"".equals(initMethodName)) {
bd.setInitMethodName(initMethodName);
}
}
else {
if (getDefaultInitMethod() != null) {
bd.setInitMethodName(getDefaultInitMethod());
bd.setEnforceInitMethod(false);
}
}
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
if (!"".equals(destroyMethodName)) {
bd.setDestroyMethodName(destroyMethodName);
}
}
else {
if (getDefaultDestroyMethod() != null) {
bd.setDestroyMethodName(getDefaultDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
}
parseLookupOverrideSubElements(ele, beanName, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, beanName, bd.getMethodOverrides());
bd.setResourceDescription(getResource().getDescription());
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
}
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
// Just apply default to singletons, as lazy-init has no meaning for prototypes.
lazyInit = getDefaultLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
return bd;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (ClassNotFoundException ex) {
throw new BeanDefinitionStoreException(
getResource(), beanName, "Bean class [" + className + "] not found", ex);
}
catch (NoClassDefFoundError err) {
throw new BeanDefinitionStoreException(
getResource(), beanName, "Class that bean class [" + className + "] depends on not found", err);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
getResource(), beanName, "Unexpected failure during bean definition parsing", ex);
}
}
上述代码详细的解析了各种元素,并且把他set到BeanDefinition中去;
最后:public static void registerBeanDefinition(
BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeanDefinitionStoreException {
// Register bean definition under primary name.
beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());
// Register aliases for bean name, if any.
if (bdHolder.getAliases() != null) {
for (int i = 0; i < bdHolder.getAliases().length; i++) {
beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);
}
}
}
很荣幸的,该BeanDefinition被加载到该BeanFactory的beanDefinitions的map中,被用来在getBean()中转换为Bean;
相关文章推荐
- Spring源代码分析(4)---BeanFactoryPostProcessor(看见的不一定是真的)
- Spring源代码分析(17)---JndiObjectFactoryBean分析(小样,花名册上有你)
- Spring源码分析之XmlbeanFactory继承关系图
- Spring源码学习-5.ProxyFactoryBean实现与源代码分析
- Spring源代码分析(10)---ProxyFactoryBean(旁敲侧击的AOP时代终于来临)
- Spring XmlBeanFactory分析
- Spring源代码分析(15)---LocalSessionFactoryBean(工厂的工厂)
- 自己重写Spring_XmlBeanFactory
- Spring中BeanFactory、ApplicationContext、xml的作用
- 5-(E-Teller源代码分析)LocalDirectorySessionFactoryBean
- Spring源码学习之XmlBeanFactory的实现
- springMVC+mybatis 进行单元测试时 main SqlSessionFactoryBean - Parsed configuration file: 'class path resource' 无限的读取xml文件
- 自己重写Spring_XmlBeanFactory_BackUp
- spring技术内幕笔记:XMLBeanFactory
- Quartz与Spring集成—— SchedulerFactoryBean的初始化分析
- Spring源码分析——BeanFactory体系之接口详细分析
- Spring XmlBeanFactory的Bean注册流程
- spring 源码分析--第二章 AbstractBeanFactory
- 【Spring源码分析】原型Bean实例化过程、byName与byType及FactoryBean获取Bean源码实现
- 自己重写Spring_XmlBeanFactory_