首先先了解一下什么是spring
Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:Core Container 中的 Core 组件是Spring 所有组件的核心,Beans 组件和 Context 组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。
spring有两个核心IOC和AOP(本篇之谈IOC)
IOC
IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spring 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。 在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
Spring 时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流行起来。
下面是IOC的初始化过程:
https://javadoop.com/post/spring-ioc这个是IOC的源码,感兴趣的可以读一读
接下来我这里实现了一个简单的IOC,话不多说上代码:
public class SimpleIoc {
private Map<String,Object> beanMap = new HashMap<>();
public SimpleIoc(String path) throws Exception {
loadBeans(path);
}
private void loadBeans(String path) throws Exception{
//获取xml里的信息
InputStream is = new FileInputStream(path);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document parse = documentBuilder.parse(is);
Element documentElement = parse.getDocumentElement();
NodeList childNodes = documentElement.getChildNodes();
//遍历xml里的bean信息
for (int i = 0; i < childNodes.getLength(); i++){
Node node = childNodes.item(i);
if(node instanceof Element){
//获取bean的id和对应的class路径
Element ele = (Element)node;
String id = ele.getAttribute("id");
String className = ele.getAttribute("class");
System.out.println(className);
Class beanClass = null;
//通过反射实例出他的对象
beanClass = Class.forName(className);
Object bean = beanClass.newInstance();
//获取他property的信息
NodeList property = ele.getElementsByTagName("property");
//遍历property信息
for(int j = 0;j<property.getLength(); j++){
Node item = property.item(j);
if(item instanceof Element) {
//获取属性名和要写入的属性值
Element pro = (Element) item;
String name = pro.getAttribute("name");
String value = pro.getAttribute("value");
//获取他的属性,并把它私有属性破坏
Field declaredField = bean.getClass().getDeclaredField(name);
declaredField.setAccessible(true);
if(value != null&&value.length()>0){
//写入属性值
declaredField.set(bean,value);
}else{
//获取ref的信息
String ref = pro.getAttribute("ref");
if(ref == null||ref.length()==0){
throw new IllegalArgumentException("ref config error");
}
//如果配置了这个bean就写入这个对应的属性
declaredField.set(bean,getBean(ref));
}
//存入map中
registerBean(id,bean);
}
}
}
}
}
public Object getBean(String name){
Object bean = beanMap.get(name);
if(bean == null){
throw new IllegalArgumentException("没有这个bean的名字");
}
return bean;
}
private void registerBean(String id,Object bean){
beanMap.put(id,bean);
}
1.加载 xml 配置文件,遍历其中的标签
2.获取标签中的 id 和 class 属性,加载 class 属性对应的类,并创建 bean
3.遍历标签中的标签,获取属性值,并将属性值填充到 bean 中
4.将 bean 注册到 bean 容器中
只需要简单的四部就可以实现一个简单的IOC,主要还是通过反射区实现这个IOC的容器。
最后附赠一张bean的生命周期图