Spring IOC/DI实现原理

本文详细阐述了Spring框架中的Inversion of Control (IOC)和Dependency Injection (DI)的概念与实现方法,通过实例演示如何通过XML配置文件进行依赖注入,并讨论其优缺点及第三方容器使用注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

** IOC/DI实现原理**

定义
IOC(Inversion of Control),即“控制反转”或DI(Dependency Injection)“依赖注入”,它不是一种技术,只是一种设计思想。
IOC
IOC(Inversion of Control,控制反转),所有的Java类(不管是JDK库中Java类,还是你自己定义Java类)
1.都可以利用Spring框架来new它们的实例化对象
2.Spring框架完成对Java类的初始化对象工作
3.Spring来负责控制对象的生命周期和对象间的关系
DI
它主要作用是动态的向某个对象提供它所需要的其他对象

某种意义上他们的意义是一样的。

实现方法
先创建一个xml格式的容器,里面可以包含我们所需要用到的类,在里面可以实现依赖注入。

<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义自己的XML格式 -->
<applicationcontext>
	<bean id="user" class="com.icss.ioc.User"></bean>
	<bean id="userDao" class="com.icss.ioc.UserDao"></bean>
	<bean id="userService" class="com.icss.ioc.UserService"></bean>
	<bean id="userController" class="com.icss.ioc.UserController">
		<ref id="userService"></ref>
	</bean>
</applicationcontext>

然后利用xml解析、反射或工厂模式就行编写代码

public class ApplicationContext {
	
	// IOC 控制反转 == DI:依赖注入 
	
	// 定义IOC容器(Hashtable)对象
	private Hashtable<String, Object> container = new <String, Object>Hashtable();
	
	public void xmlInit(String fileName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		try {
			DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			// 解析传入的XML文件
			Document  doc = db.parse(new FileInputStream(fileName));
			// 得到根节点
			Node root = doc.getDocumentElement();
			NodeList childList = root.getChildNodes();
			for(int i=0;i<childList.getLength();i++) {
				// 得到bean节点
				Node childNode = childList.item(i);
				// 得到节点属性
				NamedNodeMap nodeAttributes = childNode.getAttributes();
				// 判断节点是否有属性值
				if(nodeAttributes != null && nodeAttributes.getLength() > 0) {
					Node clazz = nodeAttributes.getNamedItem("class");
					Node id    = nodeAttributes.getNamedItem("id");
					if(clazz != null && id != null) {
						String className = clazz.getNodeValue();
						String idName    = id.getNodeValue();
						System.out.println(className);
						System.out.println(idName);
						// 依据配置文件,实例化类对象
						Object obj = Class.forName(className).newInstance();
						// 存入容器
						container.put(idName, obj);
					}
				}				
			}
			
		} catch (ParserConfigurationException | SAXException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public Object getBean(String id) throws IllegalArgumentException, IllegalAccessException {
		Object obj = this.container.get(id);
		
		// 基于注解来实现依赖注入
		Field[] fields = obj.getClass().getDeclaredFields();
		for(Field field: fields) {
			if(field.isAnnotationPresent(AutoWired.class)) {
				// 给对象obj的属性赋值
				field.setAccessible(true);
				// 就是依赖注入(核心实现)
				field.set(obj, this.container.get(field.getName()));
			}
		}
		
		return obj;
	}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
	// TODO Auto-generated method stub
	ApplicationContext applicationContext = new ApplicationContext();
	String path = ApplicationContext.class.getResource("/").getPath();
	applicationContext.xmlInit(path + "applicationContext.xml");
	
	// 从容器中获取对象:单例模式  还是非单例模式
	User user = (User)applicationContext.getBean("user");
	// IOC的依赖注入
	UserController userController = (UserController)applicationContext.getBean("userController");
	userController.login("zhangsan", "123456");
}

再使用IOC框架时,我们要注意他是一种牺牲加载速度而提高运行速度的一种框架。
同时引出第三方IOC容器,生成对象的步骤变得有些复杂。
因为它需要创建一个xml容器,所以需要配置大量文件,比较繁琐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值