** 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容器,所以需要配置大量文件,比较繁琐。