1
1
package org .m1a2st .beans .factory .xml ;
2
2
3
3
import cn .hutool .core .util .StrUtil ;
4
- import cn .hutool .core .util .XmlUtil ;
4
+ import org .dom4j .Document ;
5
+ import org .dom4j .DocumentException ;
6
+ import org .dom4j .Element ;
7
+ import org .dom4j .io .SAXReader ;
5
8
import org .m1a2st .beans .BeansException ;
6
9
import org .m1a2st .beans .PropertyValue ;
7
10
import org .m1a2st .beans .factory .config .BeanDefinition ;
8
11
import org .m1a2st .beans .factory .config .BeanReference ;
9
12
import org .m1a2st .beans .factory .support .AbstractBeanDefinitionReader ;
10
13
import org .m1a2st .beans .factory .support .BeanDefinitionRegistry ;
14
+ import org .m1a2st .context .annotation .ClassPathBeanDefinitionScanner ;
11
15
import org .m1a2st .core .io .Resource ;
12
16
import org .m1a2st .core .io .ResourceLoader ;
13
- import org .w3c .dom .Document ;
14
- import org .w3c .dom .Element ;
15
- import org .w3c .dom .NodeList ;
16
17
17
18
import java .io .IOException ;
18
19
import java .io .InputStream ;
20
+ import java .util .List ;
19
21
20
22
/**
21
23
* @Author m1a2st
@@ -34,6 +36,8 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
34
36
public static final String INIT_METHOD_ATTRIBUTE = "init-method" ;
35
37
public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method" ;
36
38
public static final String SCOPE_ATTRIBUTE = "scope" ;
39
+ public static final String BASE_PACKAGE_ATTRIBUTE = "base-package" ;
40
+ public static final String COMPONENT_SCAN_ELEMENT = "component-scan" ;
37
41
38
42
public XmlBeanDefinitionReader (BeanDefinitionRegistry registry ) {
39
43
super (registry );
@@ -54,81 +58,97 @@ public void loadBeanDefinitions(String location) throws BeansException {
54
58
public void loadBeanDefinitions (Resource resource ) throws BeansException {
55
59
try {
56
60
try (InputStream inputStream = resource .getInputStream ()) {
57
- doLoadBeanDefinitions (inputStream );
61
+ try {
62
+ doLoadBeanDefinitions (inputStream );
63
+ } catch (DocumentException e ) {
64
+ throw new RuntimeException (e );
65
+ }
58
66
}
59
67
} catch (IOException e ) {
60
68
throw new BeansException ("IOException parsing XML document from " + resource , e );
61
69
}
62
70
63
71
}
64
72
65
- private void doLoadBeanDefinitions (InputStream inputStream ) throws BeansException {
66
- Document document = XmlUtil .readXML (inputStream );
67
- Element root = document .getDocumentElement ();
68
- NodeList childNodes = root .getChildNodes ();
69
- for (int i = 0 ; i < childNodes .getLength (); i ++) {
70
- if (childNodes .item (i ) instanceof Element ) {
71
- if (BEAN_ELEMENT .equals (childNodes .item (i ).getNodeName ())) {
72
- // 解析 bean標籤
73
- Element bean = (Element ) childNodes .item (i );
74
- String id = bean .getAttribute (ID_ATTRIBUTE );
75
- String name = bean .getAttribute (NAME_ATTRIBUTE );
76
- String className = bean .getAttribute (CLASS_ATTRIBUTE );
77
- String initMethodAttribute = bean .getAttribute (INIT_METHOD_ATTRIBUTE );
78
- String destroyMethodAttribute = bean .getAttribute (DESTROY_METHOD_ATTRIBUTE );
79
- String beanScope = bean .getAttribute (SCOPE_ATTRIBUTE );
80
- // 加載bean的定義信息
81
- Class <?> clazz ;
82
- try {
83
- clazz = Class .forName (className );
84
- } catch (ClassNotFoundException e ) {
85
- throw new BeansException ("Cannot find class [" + className + "]" );
86
- }
87
- // id優先於name
88
- String beanName = StrUtil .isNotEmpty (id ) ? id : name ;
89
- if (StrUtil .isEmpty (beanName )) {
90
- // 如果id和name都為空,將類名的第一個字母轉為小寫後作為bean的名稱
91
- beanName = StrUtil .lowerFirst (clazz .getSimpleName ());
92
- }
93
- // 創建bean定義信息
94
- BeanDefinition beanDefinition = new BeanDefinition (clazz );
95
- beanDefinition .setInitMethodName (initMethodAttribute );
96
- beanDefinition .setDestroyMethodName (destroyMethodAttribute );
97
- if (StrUtil .isNotEmpty (beanScope )) {
98
- beanDefinition .setScope (beanScope );
99
- }
100
- // 解析並設置 bean的屬性
101
- for (int j = 0 ; j < bean .getChildNodes ().getLength (); j ++) {
102
- if (bean .getChildNodes ().item (j ) instanceof Element ) {
103
- if (PROPERTY_ELEMENT .equals (bean .getChildNodes ().item (j ).getNodeName ())) {
104
- // 判斷是否為property標籤
105
- Element property = (Element ) bean .getChildNodes ().item (j );
106
- String nameAttribute = property .getAttribute (NAME_ATTRIBUTE );
107
- String valueAttribute = property .getAttribute (VALUE_ATTRIBUTE );
108
- String refAttribute = property .getAttribute (REF_ATTRIBUTE );
109
-
110
- if (StrUtil .isEmpty (nameAttribute )) {
111
- throw new BeansException ("The name attribute cannot be null or empty" );
112
- }
113
- // 解析value和ref,如果都有值,則優先取ref
114
- Object value = valueAttribute ;
115
- if (StrUtil .isNotEmpty (refAttribute )) {
116
- value = new BeanReference (refAttribute );
117
- }
118
- // 將屬性設置到bean定義信息中
119
- PropertyValue propertyValue = new PropertyValue (nameAttribute , value );
120
- beanDefinition .getPropertyValues ().addPropertyValue (propertyValue );
121
- }
122
- }
123
- }
124
- // beanName不能重複
125
- if (getRegistry ().containsBeanDefinition (beanName )) {
126
- throw new BeansException ("Duplicate beanName[" + beanName + "] is not allowed" );
127
- }
128
-
129
- getRegistry ().registerBeanDefinition (beanName , beanDefinition );
73
+ protected void doLoadBeanDefinitions (InputStream inputStream ) throws DocumentException {
74
+ SAXReader reader = new SAXReader ();
75
+ Document document = reader .read (inputStream );
76
+
77
+ Element root = document .getRootElement ();
78
+
79
+ // 解析context:component-scan標簽並掃描指定包中的類,提取類信息,組裝成BeanDefinition
80
+ Element componentScan = root .element (COMPONENT_SCAN_ELEMENT );
81
+ if (componentScan != null ) {
82
+ String scanPath = componentScan .attributeValue (BASE_PACKAGE_ATTRIBUTE );
83
+ if (StrUtil .isEmpty (scanPath )) {
84
+ throw new BeansException ("The value of base-package attribute can not be empty or null" );
85
+ }
86
+ scanPackage (scanPath );
87
+ }
88
+
89
+ List <Element > beanList = root .elements (BEAN_ELEMENT );
90
+ for (Element bean : beanList ) {
91
+ String beanId = bean .attributeValue (ID_ATTRIBUTE );
92
+ String beanName = bean .attributeValue (NAME_ATTRIBUTE );
93
+ String className = bean .attributeValue (CLASS_ATTRIBUTE );
94
+ String initMethodName = bean .attributeValue (INIT_METHOD_ATTRIBUTE );
95
+ String destroyMethodName = bean .attributeValue (DESTROY_METHOD_ATTRIBUTE );
96
+ String beanScope = bean .attributeValue (SCOPE_ATTRIBUTE );
97
+
98
+ Class <?> clazz ;
99
+ try {
100
+ clazz = Class .forName (className );
101
+ } catch (ClassNotFoundException e ) {
102
+ throw new BeansException ("Cannot find class [" + className + "]" );
103
+ }
104
+ //id優先於name
105
+ beanName = StrUtil .isNotEmpty (beanId ) ? beanId : beanName ;
106
+ if (StrUtil .isEmpty (beanName )) {
107
+ // 如果没有指定beanName,則將beanName設置為類名首字母小寫
108
+ beanName = StrUtil .lowerFirst (clazz .getSimpleName ());
109
+ }
110
+
111
+ BeanDefinition beanDefinition = new BeanDefinition (clazz );
112
+ beanDefinition .setInitMethodName (initMethodName );
113
+ beanDefinition .setDestroyMethodName (destroyMethodName );
114
+ if (StrUtil .isNotEmpty (beanScope )) {
115
+ beanDefinition .setScope (beanScope );
116
+ }
117
+
118
+ List <Element > propertyList = bean .elements (PROPERTY_ELEMENT );
119
+ for (Element property : propertyList ) {
120
+ String propertyNameAttribute = property .attributeValue (NAME_ATTRIBUTE );
121
+ String propertyValueAttribute = property .attributeValue (VALUE_ATTRIBUTE );
122
+ String propertyRefAttribute = property .attributeValue (REF_ATTRIBUTE );
123
+
124
+ if (StrUtil .isEmpty (propertyNameAttribute )) {
125
+ throw new BeansException ("The name attribute cannot be null or empty" );
130
126
}
127
+
128
+ Object value = propertyValueAttribute ;
129
+ if (StrUtil .isNotEmpty (propertyRefAttribute )) {
130
+ value = new BeanReference (propertyRefAttribute );
131
+ }
132
+ PropertyValue propertyValue = new PropertyValue (propertyNameAttribute , value );
133
+ beanDefinition .getPropertyValues ().addPropertyValue (propertyValue );
134
+ }
135
+ if (getRegistry ().containsBeanDefinition (beanName )) {
136
+ //beanName不能重名
137
+ throw new BeansException ("Duplicate beanName[" + beanName + "] is not allowed" );
131
138
}
139
+ //注册BeanDefinition
140
+ getRegistry ().registerBeanDefinition (beanName , beanDefinition );
132
141
}
133
142
}
143
+
144
+ /**
145
+ * 掃描指定包下的類,提取類信息,組裝成BeanDefinition
146
+ *
147
+ * @param scanPath 指定包路徑
148
+ */
149
+ private void scanPackage (String scanPath ) {
150
+ String [] basePackages = scanPath .split ("," );
151
+ ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner (getRegistry ());
152
+ scanner .doScan (basePackages );
153
+ }
134
154
}
0 commit comments