1. public class XmlBeanFactory extends DefaultListableBeanFactory {
2.
3. private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
4.
5.
6.
7. public XmlBeanFactory(Resource resource) throws BeansException {
8. this(resource, null);
9. }
10.
11.
12. public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
13. super(parentBeanFactory);
14. this.reader.loadBeanDefinitions(resource);
15. }
16.
17. }
18.
从reader.loadBeanDefinitions(resource);可见,从外部加载xml配置文件,XmlBeanFactory是通过委托给XmlBeanDefinitionReader做的,其他都是DefaultListableBeanFactory 继承而来;
那么,我们重点来分析一些xml文件是如何把配置加载到BeanFactory中的:
1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {
2. XmlBeanDefinitionParser parser =
3. (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);
4. return parser.registerBeanDefinitions(this, doc, resource);
5. }
registerBeanDefinitions是reader是通过SAXBuilder把外部xml转换成为了Document,然后用BeanDefinition解析器来解析这个documeng文档;
1. public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource)
2. throws BeanDefinitionStoreException {
3.
4. this.beanDefinitionReader = reader;
5. this.resource = resource;
6.
7. logger.debug("Loading bean definitions");
8. Element root = doc.getDocumentElement();
9.
10. initDefaults(root);
11. if (logger.isDebugEnabled()) {
12. logger.debug("Default lazy init '" + getDefaultLazyInit() + "'");
13. logger.debug("Default autowire '" + getDefaultAutowire() + "'");
14. logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'");
15. }
16.
17. preProcessXml(root);
18. int beanDefinitionCount = parseBeanDefinitions(root);
19. if (logger.isDebugEnabled()) {
20. logger.debug("Found " + beanDefinitionCount + " <bean> elements in " + resource);
21. }
22. postProcessXml(root);
23.
24. return beanDefinitionCount;
25. }
registerBeanDefinitions方法从root元素开始处理整个document,在这里我们可以在一次看见spring给我们留出来的钩子方法,典型的模板方法的应用;
preProcessXml(root){};
postProcessXml(root){};
1. protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {
2. NodeList nl = root.getChildNodes();
3. int beanDefinitionCount = 0;
4. for (int i = 0; i < nl.getLength(); i++) {
5. Node node = nl.item(i);
6. if (node instanceof Element) {
7. Element ele = (Element) node;
8. if (IMPORT_ELEMENT.equals(node.getNodeName())) {
9. importBeanDefinitionResource(ele);
10. }
11. else if (ALIAS_ELEMENT.equals(node.getNodeName())) {
12. String name = ele.getAttribute(NAME_ATTRIBUTE);
13. String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
14. this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias);
15. }
16. else if (BEAN_ELEMENT.equals(node.getNodeName())) {
17. beanDefinitionCount++;
18. BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
19. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory());
20. }
21. }
22. }
23. return beanDefinitionCount;
24. }
parseBeanDefinitions方法中,我们开始遍历整个文档的节点,处理每个节点;并且从节点的名字,我们可以判断出三种节点,一种是<import>一种是<alias>一种是<bean>
BeanDefinitionHolder 是一个含有BeanDefinition和Bean name的存储器,我们主要来看一下spring如何从bean element 构造出BeanDefinition();
1. protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele, boolean isInnerBean)
2. throws BeanDefinitionStoreException {
3.
4. String id = ele.getAttribute(ID_ATTRIBUTE);
5. String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
6.
7. List aliases = new ArrayList();
8. if (StringUtils.hasLength(nameAttr)) {
9. String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
10. aliases.addAll(Arrays.asList(nameArr));
11. }
12.
13. String beanName = id;
14. if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
15. beanName = (String) aliases.remove(0);
16. if (logger.isDebugEnabled()) {
17. logger.debug("No XML 'id' specified - using '" + beanName +
18. "' as bean name and " + aliases + " as aliases");
19. }
20. }
21.
22. BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);
23.
24. if (!StringUtils.hasText(beanName) && beanDefinition instanceof AbstractBeanDefinition) {
25. beanName = BeanDefinitionReaderUtils.generateBeanName(
26. (AbstractBeanDefinition) beanDefinition, this.beanDefinitionReader.getBeanFactory(), isInnerBean);
27. if (logger.isDebugEnabled()) {
28. logger.debug("Neither XML 'id' nor 'name' specified - " +
29. "using generated bean name [" + beanName + "]");
30. }
31. }
32.
33. String[] aliasesArray = StringUtils.toStringArray(aliases);
34. return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
35. }
主要是获取alias,把名字用.;分开,解析成为别名;
1.
2.
3. protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName)
4. throws BeanDefinitionStoreException {
5.
6. String className = null;
7. if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
8. className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
9. }
10. String parent = null;
11. if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
12. parent = ele.getAttribute(PARENT_ATTRIBUTE);
13. }
14.
15. try {
16. ConstructorArgumentValues cargs = parseConstructorArgElements(ele, beanName);
17. MutablePropertyValues pvs = parsePropertyElements(ele, beanName);
18.
19. AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
20. className, parent, cargs, pvs, getBeanDefinitionReader().getBeanClassLoader());
21.
22. if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
23. String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
24. bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));
25. }
26.
27. if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
28. bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
29. }
30. if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
31. bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
32. }
33.
34. String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
35. if (DEFAULT_VALUE.equals(dependencyCheck)) {
36. dependencyCheck = getDefaultDependencyCheck();
37. }
38. bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
39.
40. String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
41. if (DEFAULT_VALUE.equals(autowire)) {
42. autowire = getDefaultAutowire();
43. }
44. bd.setAutowireMode(getAutowireMode(autowire));
45.
46. if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
47. String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
48. if (!"".equals(initMethodName)) {
49. bd.setInitMethodName(initMethodName);
50. }
51. }
52. else {
53. if (getDefaultInitMethod() != null) {
54. bd.setInitMethodName(getDefaultInitMethod());
55. bd.setEnforceInitMethod(false);
56. }
57. }
58.
59. if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
60. String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
61. if (!"".equals(destroyMethodName)) {
62. bd.setDestroyMethodName(destroyMethodName);
63. }
64. }
65. else {
66. if (getDefaultDestroyMethod() != null) {
67. bd.setDestroyMethodName(getDefaultDestroyMethod());
68. bd.setEnforceDestroyMethod(false);
69. }
70. }
71.
72. parseLookupOverrideSubElements(ele, beanName, bd.getMethodOverrides());
73. parseReplacedMethodSubElements(ele, beanName, bd.getMethodOverrides());
74.
75. bd.setResourceDescription(getResource().getDescription());
76.
77. if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
78. bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
79. }
80.
81. if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
82. bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
83. }
84.
85. String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
86. if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
87. // Just apply default to singletons, as lazy-init has no meaning for prototypes.
88. lazyInit = getDefaultLazyInit();
89. }
90. bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
91.
92. return bd;
93. }
94.
95. catch (BeanDefinitionStoreException ex) {
96. throw ex;
97. }
98. catch (ClassNotFoundException ex) {
99. throw new BeanDefinitionStoreException(
100. getResource(), beanName, "Bean class [" + className + "] not found", ex);
101. }
102. catch (NoClassDefFoundError err) {
103. throw new BeanDefinitionStoreException(
104. getResource(), beanName, "Class that bean class [" + className + "] depends on not found", err);
105. }
106. catch (Throwable ex) {
107. throw new BeanDefinitionStoreException(
108. getResource(), beanName, "Unexpected failure during bean definition parsing", ex);
109. }
110. }
111.
112.
上述代码详细的解析了各种元素,并且把他set到BeanDefinition中去;
最后:
1. public static void registerBeanDefinition(
2. BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeanDefinitionStoreException {
3.
4. // Register bean definition under primary name.
5. beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());
6.
7. // Register aliases for bean name, if any.
8. if (bdHolder.getAliases() != null) {
9. for (int i = 0; i < bdHolder.getAliases().length; i++) {
10. beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);
11. }
12. }
13. }
很荣幸的,该BeanDefinition被加载到该BeanFactory的beanDefinitions的map中,被用来在getBean()中转换为Bean;
2.
3. private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
4.
5.
6.
7. public XmlBeanFactory(Resource resource) throws BeansException {
8. this(resource, null);
9. }
10.
11.
12. public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
13. super(parentBeanFactory);
14. this.reader.loadBeanDefinitions(resource);
15. }
16.
17. }
18.
从reader.loadBeanDefinitions(resource);可见,从外部加载xml配置文件,XmlBeanFactory是通过委托给XmlBeanDefinitionReader做的,其他都是DefaultListableBeanFactory 继承而来;
那么,我们重点来分析一些xml文件是如何把配置加载到BeanFactory中的:
1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {
2. XmlBeanDefinitionParser parser =
3. (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);
4. return parser.registerBeanDefinitions(this, doc, resource);
5. }
registerBeanDefinitions是reader是通过SAXBuilder把外部xml转换成为了Document,然后用BeanDefinition解析器来解析这个documeng文档;
1. public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource)
2. throws BeanDefinitionStoreException {
3.
4. this.beanDefinitionReader = reader;
5. this.resource = resource;
6.
7. logger.debug("Loading bean definitions");
8. Element root = doc.getDocumentElement();
9.
10. initDefaults(root);
11. if (logger.isDebugEnabled()) {
12. logger.debug("Default lazy init '" + getDefaultLazyInit() + "'");
13. logger.debug("Default autowire '" + getDefaultAutowire() + "'");
14. logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'");
15. }
16.
17. preProcessXml(root);
18. int beanDefinitionCount = parseBeanDefinitions(root);
19. if (logger.isDebugEnabled()) {
20. logger.debug("Found " + beanDefinitionCount + " <bean> elements in " + resource);
21. }
22. postProcessXml(root);
23.
24. return beanDefinitionCount;
25. }
registerBeanDefinitions方法从root元素开始处理整个document,在这里我们可以在一次看见spring给我们留出来的钩子方法,典型的模板方法的应用;
preProcessXml(root){};
postProcessXml(root){};
1. protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {
2. NodeList nl = root.getChildNodes();
3. int beanDefinitionCount = 0;
4. for (int i = 0; i < nl.getLength(); i++) {
5. Node node = nl.item(i);
6. if (node instanceof Element) {
7. Element ele = (Element) node;
8. if (IMPORT_ELEMENT.equals(node.getNodeName())) {
9. importBeanDefinitionResource(ele);
10. }
11. else if (ALIAS_ELEMENT.equals(node.getNodeName())) {
12. String name = ele.getAttribute(NAME_ATTRIBUTE);
13. String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
14. this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias);
15. }
16. else if (BEAN_ELEMENT.equals(node.getNodeName())) {
17. beanDefinitionCount++;
18. BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
19. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory());
20. }
21. }
22. }
23. return beanDefinitionCount;
24. }
parseBeanDefinitions方法中,我们开始遍历整个文档的节点,处理每个节点;并且从节点的名字,我们可以判断出三种节点,一种是<import>一种是<alias>一种是<bean>
BeanDefinitionHolder 是一个含有BeanDefinition和Bean name的存储器,我们主要来看一下spring如何从bean element 构造出BeanDefinition();
1. protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele, boolean isInnerBean)
2. throws BeanDefinitionStoreException {
3.
4. String id = ele.getAttribute(ID_ATTRIBUTE);
5. String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
6.
7. List aliases = new ArrayList();
8. if (StringUtils.hasLength(nameAttr)) {
9. String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
10. aliases.addAll(Arrays.asList(nameArr));
11. }
12.
13. String beanName = id;
14. if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
15. beanName = (String) aliases.remove(0);
16. if (logger.isDebugEnabled()) {
17. logger.debug("No XML 'id' specified - using '" + beanName +
18. "' as bean name and " + aliases + " as aliases");
19. }
20. }
21.
22. BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);
23.
24. if (!StringUtils.hasText(beanName) && beanDefinition instanceof AbstractBeanDefinition) {
25. beanName = BeanDefinitionReaderUtils.generateBeanName(
26. (AbstractBeanDefinition) beanDefinition, this.beanDefinitionReader.getBeanFactory(), isInnerBean);
27. if (logger.isDebugEnabled()) {
28. logger.debug("Neither XML 'id' nor 'name' specified - " +
29. "using generated bean name [" + beanName + "]");
30. }
31. }
32.
33. String[] aliasesArray = StringUtils.toStringArray(aliases);
34. return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
35. }
主要是获取alias,把名字用.;分开,解析成为别名;
1.
2.
3. protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName)
4. throws BeanDefinitionStoreException {
5.
6. String className = null;
7. if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
8. className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
9. }
10. String parent = null;
11. if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
12. parent = ele.getAttribute(PARENT_ATTRIBUTE);
13. }
14.
15. try {
16. ConstructorArgumentValues cargs = parseConstructorArgElements(ele, beanName);
17. MutablePropertyValues pvs = parsePropertyElements(ele, beanName);
18.
19. AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
20. className, parent, cargs, pvs, getBeanDefinitionReader().getBeanClassLoader());
21.
22. if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
23. String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
24. bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));
25. }
26.
27. if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
28. bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
29. }
30. if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
31. bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
32. }
33.
34. String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
35. if (DEFAULT_VALUE.equals(dependencyCheck)) {
36. dependencyCheck = getDefaultDependencyCheck();
37. }
38. bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
39.
40. String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
41. if (DEFAULT_VALUE.equals(autowire)) {
42. autowire = getDefaultAutowire();
43. }
44. bd.setAutowireMode(getAutowireMode(autowire));
45.
46. if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
47. String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
48. if (!"".equals(initMethodName)) {
49. bd.setInitMethodName(initMethodName);
50. }
51. }
52. else {
53. if (getDefaultInitMethod() != null) {
54. bd.setInitMethodName(getDefaultInitMethod());
55. bd.setEnforceInitMethod(false);
56. }
57. }
58.
59. if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
60. String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
61. if (!"".equals(destroyMethodName)) {
62. bd.setDestroyMethodName(destroyMethodName);
63. }
64. }
65. else {
66. if (getDefaultDestroyMethod() != null) {
67. bd.setDestroyMethodName(getDefaultDestroyMethod());
68. bd.setEnforceDestroyMethod(false);
69. }
70. }
71.
72. parseLookupOverrideSubElements(ele, beanName, bd.getMethodOverrides());
73. parseReplacedMethodSubElements(ele, beanName, bd.getMethodOverrides());
74.
75. bd.setResourceDescription(getResource().getDescription());
76.
77. if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
78. bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
79. }
80.
81. if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
82. bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
83. }
84.
85. String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
86. if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
87. // Just apply default to singletons, as lazy-init has no meaning for prototypes.
88. lazyInit = getDefaultLazyInit();
89. }
90. bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
91.
92. return bd;
93. }
94.
95. catch (BeanDefinitionStoreException ex) {
96. throw ex;
97. }
98. catch (ClassNotFoundException ex) {
99. throw new BeanDefinitionStoreException(
100. getResource(), beanName, "Bean class [" + className + "] not found", ex);
101. }
102. catch (NoClassDefFoundError err) {
103. throw new BeanDefinitionStoreException(
104. getResource(), beanName, "Class that bean class [" + className + "] depends on not found", err);
105. }
106. catch (Throwable ex) {
107. throw new BeanDefinitionStoreException(
108. getResource(), beanName, "Unexpected failure during bean definition parsing", ex);
109. }
110. }
111.
112.
上述代码详细的解析了各种元素,并且把他set到BeanDefinition中去;
最后:
1. public static void registerBeanDefinition(
2. BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeanDefinitionStoreException {
3.
4. // Register bean definition under primary name.
5. beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());
6.
7. // Register aliases for bean name, if any.
8. if (bdHolder.getAliases() != null) {
9. for (int i = 0; i < bdHolder.getAliases().length; i++) {
10. beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);
11. }
12. }
13. }
很荣幸的,该BeanDefinition被加载到该BeanFactory的beanDefinitions的map中,被用来在getBean()中转换为Bean;