手写IOC容器通过xml文件,或者注解
68.手写一个IOC容器?
-
创建容器
-
xml处理阶段或者注解
-
创建对象(反射技术)
-
把对象放入容器
-
暴露接口给外部使用
68.1使用xml文件方式?
调用的client
package com.hou;/*** @author SmallMonkey* @Date 2023/4/10 11:38**/ public class Client {public static void main(String[] args) {//这样创建的code的耦合度太高MonkeyObject monkeyObject = new MonkeyObject();monkeyObject.say();//use this method,your code just change the id,you will earn other's objectMonkeyObject monkeyObject1 = (MonkeyObject)IOC.getBean("MonkeyObject");monkeyObject1.say();} }
IOC容器
package com.hou;import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader;import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map;/*** @author SmallMonkey* @Date 2023/4/10 11:42**/ public class IOC { // 1. 创建ioc容器: 使用k-v结构方便我们 通过方法进行获取对象static final Map<String,Object> beanMap = new HashMap<>();static{// 2. xml处理解析//把xml文件从硬盘加载到内存里面 返回二进制文件流InputStream xmlresourceStream = IOC.class.getClassLoader().getResourceAsStream("bean.xml");// 把二进制流文件转换成文本格式SAXReader saxReader = new SAXReader();try {// read xml file return a documentDocument document = saxReader.read(xmlresourceStream);//earn all the text file's root element: for search the root's bean tagsElement rootElement = document.getRootElement();List<Element> list = rootElement.selectNodes("//bean");// pull the bean one by one,from bean earn the id and class tagfor (int i = 0; i < list.size(); i++) {// take the beanElement element = list.get(i);// take the idString id = element.attributeValue("id");// take the classString aclass = element.attributeValue("class"); // 3. use reflection to create ObjectClass<?> aClass = Class.forName(aclass); // earn .classObject bean = aClass.newInstance();// create object // 4. put the object into map containerbeanMap.put(id,bean);}} catch (Exception e) {e.printStackTrace();}}// 5. expose interface for the External callpublic static Object getBean(String id){return beanMap.get(id);} }
对象:
package com.hou;/*** @author SmallMonkey* @Date 2023/4/10 11:36**/ public class MonkeyObject {public static void say(){System.out.println("我的快乐已经还是钱可以solve的。。。。。。");} }
bean.xml文件
<?xml version="1.0" encoding="utf-8"?> <beans><bean id="MonkeyObject" class = "com.hou.MonkeyObject"></bean></beans>
引入的依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.monkey</groupId><artifactId>SimpleIOC</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies> <!-- it's convinient to parse the xml document--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!--it's convinient to search the element--><dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version></dependency></dependencies></project>
68.3 使用注解的形式
自定义IOC容器的步骤如下:
- 定义注解:定义一个注解,用于标注需要被IOC容器管理的类。例如,可以定义一个
@MyComponent
注解。 - 扫描类:编写一个类扫描器,用于扫描指定包下的所有类。可以使用Java反射机制实现。
- 实例化对象:对于标注了
@MyComponent
注解的类,使用反射机制实例化对象并将其添加到IOC容器中。 - 依赖注入:对于需要依赖注入的对象,通过反射机制找到对应的依赖并进行注入。可以定义一个
@MyAutowired
注解用于标注需要进行依赖注入的字段。 - 使用IOC容器:在需要使用IOC容器的类中,使用IOC容器获取需要的实例。可以定义一个
getBean
方法用于从IOC容器中获取实例。
以上是自定义IOC容器的基本步骤。在实际应用中,还需要考虑异常处理、IOC容器的生命周期管理等问题。
- 定义注解:定义一个注解,用于标注需要被IOC容器管理的类。例如,可以定义一个