Spring IOC的Bean对象的实例化
问题:Spring是如何通过getBean方法获取到指定的类
大致流程:
- 创建对应的MyBean类提供id和class属性
- 创建实体类,实现通过配置文件解析到id和class属性,然后利用反射在找到指定的类
实现过程
1.手动创建Spring的配置文件,其中有两个标签:<beans>和<bean>,其中id属性是唯一值一般是实体类的首字母小写,class是实体类的绝对地址
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="userService" class="com.spring.Service.UserService">
</bean>
<bean id="userDao" class="com.spring.DAO.UserDao">
</bean>
</beans>
2.创建MyBean类,该类有id和class两个属性并提供构造方法和对应的get、set方法
package com.spring.Utils;
/**
* 对应Spring.xml文件中的beans标签
*
*/
public class MyBean {
private String id;
private String clazz;
public MyBean() {
}
public MyBean(String id, String clazz) {
this.id = id;
this.clazz = clazz;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
}
3.创建实现类
Tips:
1.在此处简述一下实现类通过加载spring.xml获取指定类的大致过程
2.MyFactory接口提供getBean方法通过传入id属性值获取对应的类,MyClassPathXmlApplicationContext类继承MyFactory实现getBean方法
通过带参构造器得到配置文件
通过dom4j解析xml文件,得到一个List集合(存放bean标签的id和class属性值)
通过反射得到对应的实例化对象放置在Map中(遍历list集合,通过获取对应的class属性利用Class.forName(class).newIntance()得到实例化对象)
通过id属性值获取指定的实例化对象
package com.spring.Utils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 模拟Spring的实现
*/
public class MyClassPathXmlApplicationContext implements MyFactory {
//存放从配置文件读取到的bean标签的id和class属性
private List<MyBean> beanList;
//存放实例化好的对象,通过id获取到对象
private Map<String, Object> beanMap = new HashMap<>();
/**
* 通过带参构造器得到配置文件
*
* @param fileName
*/
public MyClassPathXmlApplicationContext(String fileName) {
//通过dom4j解析xml文件,得到一个List集合
this.parseXml(fileName);
//通过反射得到对应的实例化对象放置在Map中
this.intanceBean();
}
private void parseXml(String fileName) {
//1.获取解析器
SAXReader saxReader = new SAXReader();
//2.获取URL
URL url = this.getClass().getClassLoader().getResource(fileName);
try {
//3.通过解析器解析配置文件
Document document = saxReader.read(url);
//4.获取标签
XPath xPath = document.createXPath("beans/bean");
//5.通过指定的语法解析文档对象,返回元素结合
List<Element> elementList = xPath.selectNodes(document);
//6.判断元素是否为空
if (elementList != null && elementList.size() > 0) {
//实例化beanList
beanList = new ArrayList<>();
//如果不为空则循环
for (Element element : elementList) {
//8.获取bean标签元素的属性(id和class属性)
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
//9.获取MyBean对象,将id和clazz放到对象中,再将对象设置到MyBean集合中
MyBean myBean = new MyBean(id, clazz);
beanList.add(myBean);
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 通过反射得到对应的实例化对象,放置在Map集合中
*/
private void intanceBean() {
//1.判断beanList集合是否为空,不为空则遍历集合获取该对象的id和class属性
if (beanList != null && beanList.size() > 0) {
for (MyBean bean : beanList) {
String id = bean.getId();
String clazz = bean.getClazz();
//2.通过反射得到实例化的对象
Object object = null;
try {
object = Class.forName(clazz).newInstance();
//3.将对应好的id和对象放置到map集合中
beanMap.put(id, object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
/**
* 通过id获取到对应Map中实例化好的对象,
*
* @param id
* @return object
*/
@Override
public Object getBean(String id) {
//通过id取到对应的对象
Object object = beanMap.get(id);
return object;
}
}
4.测试
package com.spring.Test;
import com.spring.DAO.UserDao;
import com.spring.Service.UserService;
import com.spring.Utils.MyClassPathXmlApplicationContext;
import com.spring.Utils.MyFactory;
public class Main {
public static void main(String[] args) {
//得到工厂的实现对象
MyFactory mc = new MyClassPathXmlApplicationContext("spring.xml");
//得到对应的实例化对象
UserService userService = (UserService) mc.getBean("userService");
userService.printInfo();
UserDao userDao = (UserDao) mc.getBean("userDao");
userDao.showInfo();
}
}
注意实现: SpringIOC中的实例化对象是单例
UserService userService = (UserService) mc.getBean("userService");
UserService userService2 = (UserService) mc.getBean("userService");
System.out.println(userService==userService2);//true,创建的两个对象是同一个对象

浙公网安备 33010602011771号