就目前来说我想很少有公司不使用spring框架了,那spring的优势我就不在这里说了,要是有朋友关心的话可以去看看百度百科怎么说的。
今天主要呢就是想自己实现一个类似spring的IOC框架。
- 首先我们确认下spring的概念,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架(来自百度百科)。其实还应该是一个容器框架。那么这就简单了,容器还能实现一对一,在我们学的Collection集合框架里面,只有map这个类库是最合适的。
- 其次,就是你得会反射。反射重要性我就不说了,现在的开源框架里面什么注解、代理都是利用了反射的技术,这个不得不会
- 再者就是解析xml,这个慕课网也有的,解析的方式有很多,只要会一种就可以了,因为其他的自己可以看官方手册。
下面就正式上代码了
首先我们定义一个接口 BeanFactory 、里面只有一个方法就是getBean,顺便说一句spring的名字也是这个BeanFactory的侧重点是Factory,就是一个能生产各种各样的Bean的这么一个类,当然spring还有一个类是XmlFactory不过这个已经过时了,不推荐使用
package com.hanson.custom.ioc;
/**
*
* @ClassName: BeanFactory
* @Description:根据ID获取对象
* @author: hanson
* @date: 2016年8月9日 上午9:44:36
*
*/
public interface BeanFactory {
public Object getBean(String id);
}
当然了首先得定义一个xml,这个xml我们就叫做beans.xml里面内容如下
<beans>
<!--id可以看作一个别名,class:用的是dao实现类不是dao接口-->
<bean id="userDao" class="com.hanson.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.hanson.service.impl.UserServiceImpl">
<!--有一个userDao属性,
property:顾名思义就是属性的意思,
name:UserServiceImpl类中的一个属性名称要和name对应
ref:由于这个属性是一个引用对象,随意用ref,非引用对象可以使用value
-->
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
然后定义一个ioc容器我打算名字都跟spring的一样,就叫ClassPathXmlApplicationContext并实现BeanFactory,另外我解析xml使用的是jdom,你也可以使用dom4j(盗梦空间)。
整体代码如下:
package com.hanson.custom.ioc;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
/**
*
* @ClassName: ClassPathXmlApplicationContext
* @Description:自定义一个Ioc容器
* @author: hanson
* @date: 2016年8月9日 上午10:10:19
*
*/
public class ClassPathXmlApplicationContext implements BeanFactory {
private static final Map<String, Object> beanMap = new HashMap<String, Object>();
public ClassPathXmlApplicationContext(String xmlPath) throws Exception {
SAXBuilder sb = new SAXBuilder();
// 构造文档对象
Document doc = sb.build(this.getClass().getClassLoader()
.getResourceAsStream(xmlPath));
// 获取根元素Beans
Element root = doc.getRootElement();
// 获取子元素bean
List<Element> list = root.getChildren("bean");
// 遍历
for (int i = 0; i < list.size(); i++) {
Element element = list.get(i);// 第i个
// 获取id的值
String id = element.getAttributeValue("id");
// 获取class的值
String className = element.getAttributeValue("class");
// 利用反射得到一个真实对象
Object obj = Class.forName(className).newInstance();
// 存入Map
beanMap.put(id, obj);
// 遍历property属性
List<Element> propertyElements = element.getChildren("property");
for (Element propertyElement : propertyElements) {
// 得到userDao
String propertyName = propertyElement.getAttributeValue("name");
String beanName = propertyElement.getAttributeValue("ref");
Object refObject = beanMap.get(beanName);
// 构造一个属性的setter方法
String methodName = "set"
+ propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1);
// 获取指定的方法
Method method = obj.getClass().getMethod(methodName,
refObject.getClass().getInterfaces()[0]);
method.invoke(obj, refObject);
}
}
}
@Override
public Object getBean(String id) {
return beanMap.get(id);
}
}
测试代码:
import com.hanson.custom.ioc.ClassPathXmlApplicationContext;
import com.hanson.service.UserService;
public class Demo {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"beans.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.say();
}
}
最后附上其他几个用到的类:
UserDao接口
package com.hanson.dao;
public interface UserDao {
public void say();
}
UserDaoImpl实现类
package com.hanson.dao.impl;
import com.hanson.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void say() {
System.out.println("Hello Ioc");
}
}
UserService接口
package com.hanson.service;
public interface UserService {
public void say();
}
UserServiceImpl实现类
package com.hanson.service.impl;
import com.hanson.dao.UserDao;
import com.hanson.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void say() {
userDao.say();
}
}
本文代码使用到的jar只用jdom。本文目的是为了便于学习spring的人了解一下IOC的实现机制。
点击查看更多内容
17人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦