依赖注入与beanMap
package com.kerwin.myssm.ioc;
import com.kerwin.myssm.util.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class ClassPathXmlApplicationContext implements BeanFactory{
private Map<String,Object> beanMap=new HashMap<String,Object>();
//这里给个默认值
String path="applicationContext.xml";
//老师说过 框架都是用无参构造去反射的,如果不写无参构造,框架就会报错
//我可能需要无参构造去 用来反射,但是我这个月无参构造没有用,我需要调用下面的有参构造,
//所以只能这么写了
public ClassPathXmlApplicationContext() {
this("applicationContext.xml");
}
public ClassPathXmlApplicationContext(String path) {
if(StringUtils.isNull(path)){
throw new RuntimeException("ICO配置文件参数出错");
}
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(path);
//1、创建DocumentBuilderFactory
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//2、创建DocumentBuilder对象
DocumentBuilder documentBuilder = null;
try {
//3、创建Document对象
documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(resourceAsStream);
//4、获取所有bean节点
//根据标签名 根据 bean标签,来获取 一个 node集合
NodeList beanList = document.getElementsByTagName("bean");
//然后循环这个集合
for (int i = 0; i < beanList.getLength(); i++) {
//这里面不叫get,叫item
Node beanNode = beanList.item(i);
if (beanNode.getNodeType() == Node.ELEMENT_NODE) {
//这个是 向上转型,用子类里面的方法
Element beanElement = (Element) beanNode;
String id = beanElement.getAttribute("id");
String className = beanElement.getAttribute("class");
//id对应实例对象
Class<?> aClass = Class.forName(className);
Object beanObj = aClass.newInstance();
//把值放进去之后,再往集合里面放
beanMap.put(id, beanObj);
//我觉的要从这里开始,毕竟我要从map里面取对象
}
}
//这里是依赖注入
for (int i = 0; i < beanList.getLength(); i++) {
//取出集合里的每一个node
Node item = beanList.item(i);
if (item.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) item;
//取出每一个node的子node List
NodeList childNodes = element.getChildNodes();
//如果这个node里面的子node List 长度不为0 就是有子node
if(childNodes.getLength()!=0){
//注意这里的 element.getAttribute("id");
//是上面第79行取出来的 item 转换的 父node
//根据这个父node id去 beanMap里面去 取值
String objectId = element.getAttribute("id");
Object thisObj = beanMap.get(objectId);
//这段就是循环子node集合
for (int j = 0; j < childNodes.getLength(); j++) {
//获取每一个子node
Node item1 = childNodes.item(j);
//如果子node 的 name=property
/**
* <beans>
* <bean id="user" class="com.kerwin.controller.UserController">
* 这个是子node 因为是标签node 所以nodeName=property
* <property name="userService" ref="UserService"/>
* </bean>
*/
if (item1.getNodeType() == Node.ELEMENT_NODE&&item1.getNodeName().equals("property")) {
Element element1=(Element) item1;
String propertyName = element1.getAttribute("name");
//这个是引用 指向 的 属性,就是我需要耦合的那个
String propertyRef = element1.getAttribute("ref");
//这个beanObj 不能找错了
//是父id 指向的类
Class<?> aClass = thisObj.getClass();
//取得这种东西 private UserService userService=null;
Field declaredField = aClass.getDeclaredField(propertyName);
declaredField.setAccessible(true);
//取得 子node 指向beanMap 集合里面的 obj
Object beanObject = beanMap.get(propertyRef);
//这步值应该就赋值进去了
//依赖注入
declaredField.set(thisObj,beanObject);
}
}
}
}
}
} catch (ParserConfigurationException | IOException | SAXException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
@Override
public Object getBean(String name) {
Object o = beanMap.get(name);
return o;
}
}
ioc需要的参数名
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf8</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</build>