【Java】手写Spring-IoC

Spring IoC所解决的问题

Spring IoC(Inversion of Control),即控制反转,也叫依赖注入DI(Dependency Injection)是将程序的控制权交给了Spring容器,从而达到控制的反转。

  • IoC降低了程序之间的耦合度。在不使用Spring框架的前提下,我们必须以创建对象的方式对两个类进行强耦合,这样,会导致我们程序的健壮性太低。如果我们程序所依赖的类出现问题,那么程序就有可能无法进行编译。而把对象创建的权利交给Spring,降低了程序之间的耦合度。
  • 程序员不需要考虑对象的创建管理,而更加专注于业务逻辑。

实现步骤

Spring提供了两种IoC容器:ApplicationContext和BeanFactory。这篇博客简单的写一个简单的Bean工厂。步骤如下:

  1. 读取xml文件,解析节点,得到类名和属性名
  2. 利用反射和类加载创建该类的实例并设置其属性值
  3. 创建set方法利用set方法进行注入

程序代码

由于我们需要对xml文件进行解析,所以这里要引入Dom4j.jar。

  1. 最重要的一点,编写自定义的配置文件。这里仿照Spring的配置文件。

<beans>

	<bean id="studentDao" class="com.spring.dao.impl.StudentDao">
		<property name="str" value="我是学生">property>
	bean>
	
	<bean id="teacherDao" class="com.spring.dao.impl.TeacherDao">
		<property name="str" value="我是老师">property>
	bean>
	
beans>
  1. 实现IoC的核心代码。
package com.spring.core;

import java.io.File;
import java.lang.reflect.Field;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class BeanFactory {
     
	
	private Document document;
	
	String contextConfigLocation = "src/spring.xml";
	
	public BeanFactory() {
     
		File file = new File(contextConfigLocation);
		SAXReader reader = new SAXReader();
		try {
     
			document = reader.read(file);
		} catch (DocumentException e) {
     
			e.printStackTrace();
		}
	}
	
	public Object getBean(String beanName) {
     
		Element root = document.getRootElement();
		List<Element> elements = root.elements();
		
		String beanLocation = null;
		String beanPropertyName = null;
		String beanPropertyVal  = null;
		
		for(Element e : elements) {
     
			if(e.attributeValue("id").equals(beanName)) {
     
				beanLocation = e.attributeValue("class");
				List<Element> propertyElements = e.elements();
				for(Element pE : propertyElements) {
     
					beanPropertyName = pE.attributeValue("name");
					beanPropertyVal = pE.attributeValue("value");
				}
			}
		}
		try {
     
			Class<?> clazz = Class.forName(beanLocation);
			Object obj = clazz.newInstance();
			Field field = clazz.getDeclaredField(beanPropertyName);
			field.setAccessible(true);
			field.set(obj, beanPropertyVal);
			return obj;
		} catch (ClassNotFoundException e1) {
     
			System.out.println(beanLocation + "类未找到");
		} catch (InstantiationException e1) {
     
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
     
			e1.printStackTrace();
		} catch (IllegalArgumentException e1) {
     
			e1.printStackTrace();
		} catch (NoSuchFieldException e1) {
     
			e1.printStackTrace();
		} catch (SecurityException e1) {
     
			e1.printStackTrace();
		}
		return null;
	}

}
  1. DAO层实现
//IuserDao.java
package com.spring.dao;

public interface IUserDao {
     
	
	public void print();

}

//StudentDao.java
package com.spring.dao.impl;

import com.spring.dao.IUserDao;

public class StudentDao implements IUserDao{
     
	
	String str;

	@Override
	public void print() {
     
		System.out.println(str);
	}

}

//TeacherDao.java
package com.spring.dao.impl;

import com.spring.dao.IUserDao;

public class TeacherDao implements IUserDao{
     
	
	String str;

	@Override
	public void print() {
     
		System.out.println(str);
	}

}
  1. Service层实现
package com.spring.service;

import com.spring.dao.IUserDao;

public class UserService {
     
	
	private IUserDao userDao;
	
	//我们要使用set方法手动注入
	public void setUserDao(IUserDao userDao) {
     
		this.userDao = userDao;
	}
	
	public void print() {
     
		System.out.println("我是service层方法");
		userDao.print();
	}
	
}
  1. Controller层实现。
package com.spring.controller;

import com.spring.core.BeanFactory;
import com.spring.dao.impl.TeacherDao;
import com.spring.service.UserService;

public class TestController {
     
	
	public static void main(String[] args) {
     
		BeanFactory beanFactory = new BeanFactory();
		UserService userService = new UserService();
		//这里是我们程序运行时需要更改的地方
		userService.setUserDao((IUserDao)beanFactory.getBean("teacherDao"));
		userService.print();
	}

}

程序测试

我们只需改变其所注入的Bean的名称。
【Java】手写Spring-IoC_第1张图片
【Java】手写Spring-IoC_第2张图片

你可能感兴趣的:(Java)