浅谈Spring IOC (IOC模型)
Posted HUTEROX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Spring IOC (IOC模型)相关的知识,希望对你有一定的参考价值。
前言
关于目前我们先解读关于Spring的IOC部分,这个也是个大头。下面是某个大佬的文章,不过这里并不是说查看人家的文章,而是通过自己的理解实现一个简单的IOC容器,后面再将其“标准化”和Spring对接实现对Spring的拓展。当然我们现在这边还是容器部分的实现。这部分实现了,那个后面的不就自然而然嘛。
- IDEA编译Spring源码
- Spring源码(一)-Bean的定义-BeanDefinition
- Spring源码(二)-XML文件的读取-BeanDefinitionReader
- Spring源码(二-1)-XML文件的读取-bean标签
- Spring源码(二-2)-lookup-method、replaced-method标签
- Spring源码(三)-Bean工厂-BeanFactory
- Spring源码(四)-FactoryBean与getBean
- Spring源码(五)-获取Bean-getBean
- Spring源码(六)-创建Bean流程-createBean
- Spring源码(七)-Supplier、工厂方法实例化Bean-createBeanInstance
- Spring源码-BeanPostProcessor
- Spring源码-Aware接口
(我本人没有深入去了解,我们先根据自己的理解去实现一个我们自己理解的IOC,然后再去对比修正)
单纯的通过文章目录 不难发现其实关于 这部分的实现大致还是三大块
- 对XML的解析读取(前面的BeanDefinition我认为其实还是对Bean怎么在XML当中自动存储进行初始化定义)
- 对读取到的 XML 文件解析得到对象
- 通过对象进行组装,实现相应的模式(例如功单例模式,多例模式,包括后面的AOP面向切面也是在这部分后面)
现在我们大致应该是知道了一个流程,这个流程其实和先前的谋篇文章的思路有点类似。
其实这里也是使用到了我们类似的一个模式
那么这里为了规范我们自己去简单规划一下,还是大体分三个部分。
说明
BeanDaulft
首先是 BeanDaulft 这个是对Java Bean 进行一个简单的初始化,如何对一个类进行存储定义。这里考虑到文章的篇幅和简单实现,所以我们这次不是通过 XML 去实现,而是通过 peropriter 配置文件去实现,对我们这边容器进行定义
BeanFactory
这个玩意主要就是读取配置文件当中的玩意,之后我们把配置文件当中的内容组合在一块,也就是通过java反射和内省(Class.forname(),Introspector)我们读取到IO流然后组装。
BuilderBean
这个其实是对前面的那两个玩意进行调配其实,也就是我们获取一个搞定好的BeanFactory,之后我们通过BeanFactory进行对象的创建。这个非常重要,因为如果我们想要实现单例模式,或者多例模式我们就必须得到一个BeanFactory然后对其进行封装。
对比Spring操作
通过我们说明我们大致明白了每一个包所充当的功能角色。那么具体实现的结果其实大致会和前面那篇文章 实现 AOP 的类似
package day07;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
public class AOPDomeTest
public static void main(String[] args)
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("day07/bean.properties");
try
BeanFactory beanFactory = new BeanFactory(new InputStreamReader(in,"utf8"));
SendAgentFindHouse sendAgentFindHouse = (SendAgentFindHouse) beanFactory.getBean("bean.SendAgentFindHouse");
BuyHouse buyHouse = (BuyHouse) sendAgentFindHouse.SendAgent();
buyHouse.buyHouse();
catch (UnsupportedEncodingException e)
// TODO Auto-generated catch block
e.printStackTrace();
这个是那个AOP最终调用的代码 你会发现一个神奇的玩意叫做:
beanFactory.getBean("bean.SendAgentFindHouse");
之后你再对比Spring最原始使用xml注解实现的getBean() 的调用
这里Spring通过上下文 Context 来获取了我们的配置文件,这个配置文件放了这个东西
我通过id Hello 我就是获取了 com.huterox.pojo.Hello 这个Class 然后通过反射去做,只不过前面是那个通过
懂了吧,你再看看我先前的项目结构(这些都是防在 day07这个包下面的(至于是不是第七天学的我就不知道了,有点遗憾的是那个源代码找不到了,不然我不会去再一遍))
OK 那么现在我们通过对比 Spring 最原始的一个操作之一 搞清楚了我们这个几个包到底要做啥。那么我们就实际动动小手
我们这边为了先简便一点,我们就先把 properites 文件命名为 Application 毕竟我们今天没有上下文支持。
大概长这样,目前(不着急,咱们还是要慢慢优化滴)
那么首先我们这个还是比较原始滴,在我们自己定义一个类的时候要写你想要对应的ID 和所在包名的类
也就是先前那种写法
后面我在通过注解的方式来实现,还是比较简单滴。
V0.001 初步模型
OK那么现在我们开始来探讨一下先如何实现那个获取配置文件,然后就拿到我们生成的对象的操作。
效果
行,咱们先来看看结果
首先咱们是在 Test包下面创建了一个Hello类
这里咱们还是先探讨最简单的模式,假设我们只需要简单的去让它创建一个对象。先不需要去给具体的对象值(当然这个其实也是用反射的厉害之处,管你是不是公开的,私有的我可以给你搞出来)
这个时候你可能有点迷糊,这玩意我直接new不香吗。首先我们搞清楚咱们的需求,如果我们是自己写的项目,那当然每一个包都可以管理的好好的。但是如果这是一个大型项目,我们必然需要一个机制来统一管理我们所有的类,也可说是 “中央集权” 那么为什么要用反射呢。要知道直接 new 的效率可比反射高多了(具体可以查看这篇文章(Java反射和new效率对比)这不是我写的),很简单为了拓展未知业务,为了方便统一处理。通过这个我可以让我的核心组件知道可以使用由别人创建的类,举个例子就是 Spring。
实现
说了那么多咱们来看看大概的实现,由于是最简单的版本,所以嘛,超级简单的。
咱们这里不像那个 Spring 需要那么多过滤之类的(我敢打赌 Spring 对 XML 的支持代码都得一大堆)咱们就直接获取配置文件就可以。
而且 咱们现在还没有用到注解,而且不需要实现某些模式,所以直接搞。那么这里就用到了两个类实现。
由上而下:
package BeanDaulft;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
public class BeanReader
private InputStreamReader inputStreamReader;
private Properties properties = new Properties();
public BeanReader()
public BeanReader(InputStreamReader in) throws IOException
this.inputStreamReader = in;
properties.load(in);
public Properties GetBeanReader()
return properties;
public Properties GetBeanReader(String FileName) throws IOException
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(FileName);
properties.load(new InputStreamReader(in,"utf8"));
return properties;
package BeanFactory;
import BeanDaulft.BeanReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
public class BeanMake
private Properties prop;
private BeanReader beanReader;
public BeanMake(String Path) throws IOException
beanReader = new BeanReader();
Properties properties = beanReader.GetBeanReader(Path);
this.prop = properties;
public BeanMake(Properties prop)
this.prop = prop;
public Object getBean(String name) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException
Class<?> beanClass = Class.forName(prop.getProperty(name));
Object bean = beanClass.getConstructor().newInstance();
return bean;
接下来就是调用嘛
package Test;
public class Hello
public void SayHello()
System.out.println("博主真真帅");
Hello = Test.Hello
package Test;
import BeanFactory.BeanMake;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
public class Test
public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException
BeanMake beanMake = new BeanMake("Application.properties");
Hello hello = (Hello) beanMake.getBean("Hello");
hello.SayHello();
没错,现在我们就相当于有了一个容器。
至于 先前 Spring 老是扯皮的 IOC 反转控制 ,其实也是这个,所谓反转,其实就是依赖转移,我们通过 BeanFactroy去创建我们的对象
而不是直接 new 一个 ,好处是方面拓展。那么看完这个咱们就可以再去好好看看Spring源码了~
总结
这个呢,其实还只是我自己的理解,不太清楚对不对。不过慢慢纠正嘛,我这个就是单纯的看了看目录,思维导图加上自己的Spring 的一个体验 觉得应该是这样的。那么之后就是 在未来将 开设
Spring 源码研读,JAVA JVM 学习以及 Go 语言专栏。
那么今天暂时到这里,后面我再看看然后验证猜想对不对,实现实现咱们这个小Dome。
最最后 就是那个 关于 WhiteHole 博客社区的源码,这个项目还在开发当中,等能够上线了在推送GitHub,主要是现在缺一个后台管理的前端模板,这个我后面找找。然后就快期末了时间不太够~
以上是关于浅谈Spring IOC (IOC模型)的主要内容,如果未能解决你的问题,请参考以下文章