1. 目标
以面向过程的方式完成基本的IoC容器下一篇基于该实现完成spring基础BeanFactory的改造。下面的代码只会完成最为基础的部分,异常处理多种标签的解析不写入该实现中。
手写IoC是为了帮助理解Spring IoC容器。
2. Spring Xml的封装分析
Spring IoC容器帮助使用者完成了大量的基础工作,是Spring最为核心的部分。下面先来看看一个基本Xml封装
每个标签封装成一个BeanDefinition
对象记录类的类型,id,初始化方法,作用域,以及字段值信息。若字段值为直接类型使用TypedStringValue
封装,如果是ref引用了其他变量使用RuntimeBeanReference
封装。
有了这些对应感谢,相信就无需再解释这些类是干什么用的了。接下里写是具体实现。
ps:这里的Service就是个透传什么都没干,Dao的实现给在下面。不要太关注这个wxyBatisV1,直接写个JDBC实现就可以,甚至直接返回个User对象都OK,这不是要讨论的重点。
public class UserDaoImpl implements IUserDao {
private WxyBatisV1 wxyBatisV1;
public UserDaoImpl() {
}
public void init() {
System.out.println("UserDaoImpl初始化方法被调用");
}
public WxyBatisV1 getWxyBatisV1() {
return wxyBatisV1;
}
public void setWxyBatisV1(WxyBatisV1 wxyBatisV1) {
this.wxyBatisV1 = wxyBatisV1;
}
@Override
public User getUserById(Integer id) {
return wxyBatisV1.getUserById(id);
}
}
3. 手写基本Spring IoC容器
写之前先来看看需要什么(下面给出的代码很多异常、null的处理都没有给出主要聚焦核心流程)
1.为了读取配置类完成解析封装,先搞个流处理。xml的解析用dom解析或者sax解析看读者哪个熟悉了。
String location = "beans.xml";
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(location);
Document document = createDocument(inputStream);
// 解析上面那个简单的xml
parseBeanDefinitions(document.getRootElement());
2.为了记录BeanDefinition要弄个东西存起来
// 存储beanDefinition
private Map<String, BeanDefinition> beanDefinitions = new HashMap<>();
3.为了处理BeanDefinition生产的单例bean,又要弄个东西存一下
// 做单例的缓存
private Map<String, Object> singletonObjects = new HashMap<>();
4.获取bean需要访问缓存singletonObjects
没有就使用BeanDefinition创建
Object singletonObject = sin