手寫SpringIOC架構
什麼是SpringIOC
什麼是SpringIOC,就是把每一個bean(實體類)與bean(實體了)之間的關系交給第三方容器進行管理。
Xml配置:
<beans>
<bean id="user1" class="com.itmayiedu.entity.UserEntity">
<property name="userId" value="0001"></property>
<property name="userName" value="何傑"></property>
</bean>
<bean id="user2" class="com.itmayiedu.entity.UserEntity">
<property name="userId" value="0002"></property>
<property name="userName" value="張三"></property>
</bean>
</beans>
Java代碼:
//1.讀取springxml配置
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
//2.擷取bean對象
TestService testService = (TestService) classPathXmlApplicationContext.getBean("testService");
System.out.println(testService.test());
什麼是SpringIOC底層實作原理
- 1.讀取bean的XML配置檔案
- 2.使用beanId查找bean配置,并擷取配置檔案中class位址。
- 3.使用Java反射技術執行個體化對象
-
4.擷取屬性配置,使用反射技術進行指派。
詳細步驟
1.利用傳入的參數擷取xml檔案的流,并且利用dom4j解析成Document對象
2.對于Document對象擷取根元素對象<beans>後對下面的<bean>标簽進行周遊,判斷是否有符合的id.
3.如果找到對應的id,相當于找到了一個Element元素,開始建立對象,先擷取class屬性,根據屬性值利用反射建立對象.
4.周遊<bean>标簽下的property标簽,并對屬性指派.注意,需要單獨處理int,float類型的屬性.因為在xml配置中這些屬性都是以字元串的形式來配置的,是以需要額外處理.
5.如果屬性property标簽有ref屬性,說明某個屬性的值是一個對象,那麼根據id(ref屬性的值)去擷取ref對應的對象,再給屬性指派.
6.傳回建立的對象,如果沒有對應的id,或者<beans>下沒有子标簽都會傳回null
建立實體類
public class User {
private String userId;
private String userName;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
使用反射技術完成Java代碼
public class ClassPathXmlApplicationContext {
private String pathXml = null;
public ClassPathXmlApplicationContext(String pathXml) {
this.pathXml = pathXml;
}
public Object getBean(String beanId) throws Exception {
if (StringUtils.isEmpty(beanId)) {
throw new Exception("beanId is null");
}
SAXReader saxReader = new SAXReader();
Document read = saxReader.read(this.getClass().getClassLoader().getResource(pathXml));
// 擷取到根節點
Element rootElement = read.getRootElement();
// 根節點下所有的子節點
List<Element> elements = rootElement.elements();
for (Element element : elements) {
// 擷取到節點上的屬性
String id = element.attributeValue("id");
if (StringUtils.isEmpty(id)) {
continue;
}
if (!id.equals(beanId)) {
continue;
}
// 使用java反射機制初始化對象
String beanClass = element.attributeValue("class");
Class<?> forName = Class.forName(beanClass);
Object newInstance = forName.newInstance();
List<Element> propertyElementList = element.elements();
for (Element el : propertyElementList) {
String name = el.attributeValue("name");
String value = el.attributeValue("value");
Field declaredField = forName.getDeclaredField(name);
declaredField.setAccessible(true);
declaredField.set(newInstance, value);
}
return newInstance;
}
return null;
}
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext classPath = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) classPath.getBean("user2");
System.out.println(user.getUserId() + "---" + user.getUserName());
}
}
Maven坐标
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>