手写Spring(IOC/DI)
Spring(IOC/DI )
IOC/DI 介绍
- IOC:Inversion Of Control (创建对象由自己创建变成了容器创建和管理)。
- DI: Dependcy injection (注入的参数包含构造参数和属性)。
- IOC/DI 是核心,分析为什么需要IOC和DI,怎么去实现他们。
为什么需要IOC/DI
需要原因
我们开发应用有了三层架构(Controller Service Dao)
首先是3个层的对象创建,没有Spring之前,我们就是直接使用 new Controller() 对象 Controller 里面包含一个或多个Service对象(正常使用 在属性 Service s = new ServiceImp()) 这样子去实现的。
但是呢:这是违背设计原则的:里氏替换原则 开闭原则 (我一旦实现类变了就需要需改原有代码)使用设计模式进行优化
现在使用工厂模式 创建对象 ,如果改变就使用策略模式进行替换
但是这样会使我们的工厂会很多代码很冗余。
- 我们需要做成一个公共的工厂专门去做对象(bean)的初始化(IOC)
我们先定义一些接口规范应对我们的bean创建
- 定义我们bean工厂(工厂的规范)
BeanFactory 接口
getBean(beanName)
//bean工厂默认实现
DefaultBeanFactory --> 实现类 保存bean的形式 map (定位快) - 工厂怎么创建类(需要注册需要管理的类)
// bean的注册 xml 注解 方式获取然后注册到工厂里面 map里面
BeanDefinitionRegistry
-registerBeanDefinition(beanName,beanDefinition)
-getBeanDefinition(beanName)
-containsBeanDefinition(beanName) - 注册的时候是怎么包含一个类的信息的(BeanDefinition)
分析一下:getFactoryMethodName 和 getFactoryBeanName 和 getInitMethodName 和 getDestroyMethodName 作用- getInitMethodName 指定bean的初始化方法(非构造方法)
- getFactoryBeanName 你可以指定一个构造bean的工厂类(但是这个工厂类的对象必须是在容器里面)
- getFactoryMethodName 指定一个工厂类的指定工厂方法(同上)
- getDestroyMethodName (容器关闭时候释放的方法)
- 3个之前的关系
注册bean (BeanDefinitionRegistry) 里面使用了 bean的定义(BeanDefinition)
工厂的实现(DefaultBeanFactory) 肯定实现了BeanFactory接口 ,但是里面需要用到了注册了的bean的信息才能给你取创建对象,那时要包含BeanDefinitionRegistry还是要继承它,从设计模式角度,多使用组合和聚合 比继承更灵活,但是这边的话,但是这边使用的是 继承关系,因为外界是不知道注册接口的存在的所以你的工厂必须要提供注册方法(注册接口主要是给不同注册方式去实现的XML或注解)
- 依赖注入(DI)Dependcy injection
- IOC是解决了对象创建和管理的问题
- DI 是解决了对象直接的关系问题 (属性 构造参数)
- 注意:属性的注入设计到了一个循环依赖(在bean构造时候的循环依赖是不行的)
- DefaultBeanFactory 默认的方法里面去实现 getBean (简单的介绍后面附上源码地址 )
// 构造方法来构造对象 createInstanceByConstructor
// 静态工厂方法 createInstanceByStaticFactoryMethod
// 工厂bean方式来构造对象 createInstanceByFactoryBean
对于我们DI需要解决的是(属性的循环依赖) DI的前提条件就是IOC (所有的bean对象需要在我们的工厂里面管理和处理)