Spring IOC 容器 Bean对象实例化模拟
思路:
1.定义Bean 工厂接口,提供获取bean方法
2.定义Bean工厂接口实现类,解析配置文件,实例化Bean对象
3.实现获取Bean方法
新建Maven项目
1.创建Maven的普通java项目
2.设置项目的坐标、名称、工作空间
3.设置项目的 Maven 环境
定义 Bean 属性对象
package com.xxxx.po;
/**
* Bean对象
* 用来接收配置文件(spring.xml)中,bean标签的id和class属性值
*/
public class MyBean {
private String id;//bean标签的id属性
private String clazz;//bean标签的class属性
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;
}
}
添加 dom4j 和 XPath 坐标依赖
<!-- dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- XPath -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
准备自定义配置文件
spring.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="userService" class="com.xxxx.service.UserService"/>
<bean id="userDao" class="com.xxxx.dao.UserDao"/>
</beans>
定义 Bean 工厂接口
package com.xxxx.factory;
/**
* 工厂接口
* 定义获取bean对象的方法接口
*/
public interface MyFactory {
//通过id属性获取bean对象
public Object getBean(String id);
}
定义 Bean 接口的实现类
package com.xxxx.factory;
import com.xxxx.po.MyBean;
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;
/**
* 工厂接口的实现类
* 1.获取要解析的配置文件
* 2.解析配置文件(dom4j),将解析好的bean标签设置到对应的bean对象中,再将bean对象设置到集合中
* 3.得到集合中的Bean对象,并将对应的id与其实例化好的Bean设置到map中
*
*/
public class MyClassPathXmlApplication implements MyFactory{
private List<MyBean> beanList = null;//存放解析好的bean标签集合
private Map<String ,Object> beanMap = new HashMap<>();//实例化好的bean对象放入map
//获取要解析的配置文件
//通过带参构造器得到相关配置文件
public MyClassPathXmlApplication(String fileName){
//解析配置文件,将结果设置到list中
this.parseXml(fileName);
//实例化Bean对象,将结果设置到map中
this.instanceBean();
}
/**
* 解析XML配置文件
* @param fileName
*/
private void parseXml(String fileName) {
//获取解析器
SAXReader saxReader = new SAXReader();
//得到要解析的配置文件的url
URL url = this.getClass().getClassLoader().getResource(fileName);
try {
//通过解析器解析xml文件(spring.xml),返回Document对象
Document document = saxReader.read(url);
//通过xpath语法,获取beans标签下的所有bean标签
XPath xPath = document.createXPath("beans/bean");
//通过XPath语法获取要解析的指定元素
List<Element> elementList = xPath.selectNodes(document);
//判断标签集合是否存在
if(elementList != null && elementList.size()>0){
//实例化集合
beanList= new ArrayList<>();
//遍历集合
for(Element el : elementList){
//获取元素的id属性值和class属性值
String id = el.attributeValue("id");
String clazz = el.attributeValue("class");
//将id和clazz的值设置到对应的bean对象中
MyBean myBean = new MyBean(id,clazz);
//将对应的bean对象设置到集合中
beanList.add(myBean);
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 实例化Bean对象
* 1.得到对应的bean对象中的id和class
* 2.通过class属性值(类路径)得到对应的实例化对象
* 3.将id和实例化的对象分别设置到map的键和值中
*/
private void instanceBean() {
//判断bean对象的集合是否存在
if(beanList != null && beanList.size()>0){
//遍历
for(MyBean bean : beanList){
try {
//键
String id = bean.getId();
//值(实例化好的对象)
//通过class的值(类路径)得到实例化对象
Object object = Class.forName(bean.getClazz()).newInstance();
//设置map
beanMap.put(id,object);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 通过id获取map中指定的实例化对象
* @param id
* @return
*/
@Override
public Object getBean(String id) {
return beanMap.get(id);
}
}
创建与配置文件中对应的 Bean 对象
UserService.java
package com.xxxx.service;
public class UserService {
public void test(){
System.out.println("UserService...");
}
}
UserDao.java
package com.xxxx.dao;
public class UserDao {
public void test(){
System.out.println("UserDao...");
}
}
测试是否可以获取实例化的Bean对象
package com.xxxx;
import com.xxxx.dao.UserDao;
import com.xxxx.factory.MyClassPathXmlApplication;
import com.xxxx.factory.MyFactory;
import com.xxxx.service.UserService;
/**
* 模拟Spring IOC 容器 Bean对象实例化
*/
public class App {
public static void main(String[] args) {
//得到上下文环境
MyFactory factory = new MyClassPathXmlApplication("spring.xml");
//得到实例化好的对象
UserService userService = (UserService) factory.getBean("userService");
UserDao userDao = (UserDao) factory.getBean("userDao");
UserDao userDao2 = (UserDao) factory.getBean("userDao");
System.out.println(userDao);
System.out.println(userDao2);
userService.test();
userDao.test();
}
}
测试结果
com.xxxx.dao.UserDao@4e515669
com.xxxx.dao.UserDao@4e515669
UserService...
UserDao...