在网上看了很多大神写的关于springIOC的博客,有很多都写的十分的深入,而且将IOC和DI讲的也很透彻,但是对于我们这些理论知识不是太好的小白来说,还是有些复杂了。所以今天我使用java的反射写一个简单版的springIOC的实现原理,很简单的删节版本哦。
首先我们谈谈什么是IOC,什么又是DI。(摘抄的网上解释)ioc(inverse of control )控制反转:所谓控制反转就是把对象(bean)对象和维护对象(bean)之间的关系的权利转移到Sqring容器中去了(ApplicationContext.xml)而程序本身不在维护了。di(dependency injection)依赖注入:实际上DI和IOC是同一个概念,因为在ApplicationContext.xml配置文件中bean和bean之间通过ref来维护的时候是相互依赖的,所以又叫做依赖注入。也就是控制反转。
直接上代码:
public class User {
private String userId;
private String userName;
public User(){
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="user1" class="com.lzf.test.User">
<property name="userId" value="0001"></property>
<property name="userName" value="小明"></property>
</bean>
<bean id="user2" class="com.lzf.test.User">
<property name="userId" value="0002"></property>
<property name="userName" value="张三"></property>
</bean>
</beans>
上面是事先准备好的一个bean和xml。
public class ClassPathXmlApplicationContext {
private String xmlPath;
public ClassPathXmlApplicationContext(String xmlPath){
this.xmlPath = xmlPath;
}
public Object getBean(String beanId) throws DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException{
//1.解析xml
SAXReader saxReader = new SAXReader();
Document read = saxReader.read(this.getClass().getClassLoader().getResource(xmlPath));
//如果read为null则返回
if(read==null){
return null;
}
//2.获取里面Dom
//获取根节点的dom
Element rootElement = read.getRootElement();
//获取其节点下的集合
List<Element> elements = rootElement.elements();
if(elements.size()<=0){
return null;
}
Object obj = null;
for (Element element : elements) {
String id = element.attributeValue("id");
//如果id为空
if(StringUtils.isEmpty(id)){
return null;
}
//如何id不为beanId
if(!id.equals(beanId)){
continue;
}
//获取bean的class
String Beanclass = element.attributeValue("class");
//反射获取Class
Class<?> forName = Class.forName(Beanclass);
//实例化类
obj = forName.newInstance();
//获取子节点的集合
List<Element> elements2 = element.elements();
for (Element element2 : elements2) {
//获取xmlbean里的name和value
String name = element2.attributeValue("name");
String value = element2.attributeValue("value");
//为User类注入xml里的值
Field nameUser = forName.getDeclaredField(name);
//设置为可写
nameUser.setAccessible(true);
nameUser.set(obj, value);
}
}
return obj;
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, DocumentException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("user.xml");
User user = (User)applicationContext.getBean("user1");
System.out.println("userName:"+user.getUserName()+"----"+"userId:"+user.getUserId());
}
}
实际上springIOC最浅的实现原理就是解析xml然后使用java的反射机制将读取到的数据返回给bean。当然实际上的spring写的要复杂的多。我也只是为了更好的理解它,才做了简化。使用getBean我们就能拿到自己想要的实体类了。