1、实现思路
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userDao" class="com.jan.dao.IUserDao"></bean>
<bean id="iservice" class="com.jan.service.IService">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
1、要实现ioc首先我们需要一个容器,容器我们选择map集合来表示。
2、Ioc实现原理 、解析出上面bean标签中的id和class元素的属性值,其中class的属性值是全类名。拿到全类名后就可以通过反射创建对象实例,在将id属性值作为map的key将创建出来的实例对象添加map容器中。
3、DI依赖注入原理 、解析出property 标签中的name 和 ref,其中name是要进行注入的类中字段的名字,ref是要注入的引用(对象)当然也可以注入基本类型和String类型。主要原理还是通过set方法进行注入,java中set方法的规范约定字段的set方法是“set” + “字段名首字母大写” ,拿到字段名后可以拼接出是“set” + “字段名首字母大写”的方法名,通过反射就可以进行方法调用实现注入。
2、实现代码
模拟持久层
/**
* @Author: jan
* @Description: TODO
* @DateTime: 2022/7/14 9:38
* @Version 1.0
**/
public class IUserDao {
public void save() {
System.out.println("保存用户");
}
}
模拟业务层
import com.jan.dao.IUserDao;
/**
* @Author: jan
* @Description: TODO
* @DateTime: 2022/7/14 9:39
* @Version 1.0
**/
public class IService {
private IUserDao userDao;
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
1、BeanFactory接口
/**
* @Author: jan
* @Description: IOC容器
* @DateTime: 2022/7/14 9:41
* @Version 1.0
**/
public interface BeanFactory {
public Object getBean(String key);
}
2、ClassPathXmlApplicationContext 实现类
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: jan
* @Description: IOC容器实现类
* @DateTime: 2022/7/14 9:43
* @Version 1.0
**/
public class ClassPathXmlApplicationContext implements BeanFactory{
// 容器
private Map<String,Object> beans = new HashMap<>();
// 从容器中获取bean
@Override
public Object getBean(String key) {
return beans.get(key);
}
public ClassPathXmlApplicationContext(String XmlPath) throws Exception{
// 读取xml配置
SAXBuilder saxBuilder = new SAXBuilder();
// 文档对象类型
Document document = saxBuilder.build(XmlPath);
// 获取根元素
Element rootElement = document.getRootElement();
// 获取根元素中的所有子元素
List<Element> elements = rootElement.getChildren();
// 遍历beans中的bean子元素
for (Element element : elements) {
// ---------------------IOC 底层实现代码---------------------
// 获取属性的值
String id = element.getAttributeValue("id");
String aClass = element.getAttributeValue("class");
// 反射创建实例
Object instance = Class.forName(aClass).newInstance();
// 将实例放进容器中进行管理
beans.put(id,instance);
// ---------------------IOC 底层实现代码---------------------
// spring ioc 控制反转功能
List<Element> list = element.getChildren("property");
for (Element element1 : list) {
// ---------------------DI 底层实现代码---------------------
String name = element1.getAttributeValue("name");
String ref = element1.getAttributeValue("ref");
// 从容器中获取要注入的对象
Object obj = beans.get(ref);
// 拼接“set” + “字段名首字母大写”的方法名
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
// 反射调用set方法进行依赖注入
Method method = instance.getClass().getMethod(methodName, obj.getClass());
// 反射调用setXXX 进行属性注入
method.invoke(instance,obj);
// ---------------------DI 底层实现代码---------------------
}
}
}
}
3、进行测试
import com.jan.service.IService;
/**
* @Author: jan
* @Description: TODO
* @DateTime: 2022/7/14 10:04
* @Version 1.0
**/
public class Main {
public static void main(String[] args) throws Exception {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("D:\dev\project\springioc\ioc\beans.xml");
IService iservice = (IService) beanFactory.getBean("iservice");
iservice.save();
}
}