前两天写简历,写了一句:精通Spring IoC容器。怎么个精通法?仍是本身动手写个IOC容器吧。java
什么是IoC(Inversion of Control)?什么是DI(Dependency Injection)?很少解释,本身Google!但愿你先明确几个概念,该文章不作这方面的阐述,重点关注如何实现。我将用简要的语言从需求,设计,代码三方面来描述一个简单的IoC容器,来讲明IoC容器是如何帮咱们建立类的实例、如何实现依赖注入,最后会奉上一个完整的IoC容器实例。git
1、需求,实现一个IoC容器算法
一、需求描述:spring
二、图中一些概念:编程
(1)服务元数据:一种是咱们的编译好的类文件,即.class文件;另外一种是xml文件。你能够理解为spring的注解和xml两种配置bean的方式。设计模式
(2)服务定义信息:由元数据转换来的信息,即读取bean中的注解或xml文件,获取到的对象描述信息。缓存
(3)服务提供者:对象的实例。你能够理解为Spring中Bean的实例;数据结构
(4)服务定义信息存储区:保存服务定义信息的地方;ide
(5)服务提供者实例缓存区:保存服务提供者的地方。工具
三、流程描述:
(1)建立容器:初始化容器,实质是初始化容器内部的工厂,而后读取元数据,转化为服务定义信息,保存到服务定义信息存储区;
(2)调用服务提供者A的方法:获取该服务提供者A的服务定义信息,判断是否有缓存,若是有,直接调用缓存中的A;若是没有,据此实例化A,放入缓存,若发现A依赖其余服务提供者B,则查找缓存,若是有,将缓存中的B注入A;不然实例化B,注入到A中,同时放入缓存。以此类推。
(3)上面两个是核心流程,在此基础上,扩展了几个流程:
1)获取全部服务提供者定义信息;
2)获取全部服务提供者实例;
3)获取某个服务提供者实例;
4)热加载新的服务提供者。
2、设计,根据需求,以面向对象为基础,融合几种设计模式来勾勒IOC容器。
注:因为源码较多,会占很大篇幅,因此只给出了部分核心代码实现,全部代码见个人CSDN CODE,见文章末尾的说明。
一、UML,类图
二、设计说明
从类图能够看出,严格按照面向接口的方式编程,松耦合的设计保证了可扩展性和灵活性。
我定义了一套实现IOC容器的规范,这套规范的直接表现就是一组接口及其关系,有没有一点J2EE的感受。而后,我给出了各个接口的一个默认实现,也就是给出了一个容器的默认实现。其余开发者既能够所有个人默认实现或所有使用自定义实现,也能够部分组件使用默认实现,部分组件实现自定义实现。
三、介绍接口与默认实现,即扩展点。
(1)Container接口及默认实现
核心代码:
import com.tgb.Entity.BeanEntity; import com.tgb.data.IDataContext; /** * @Author : JiaLin * @Email : shan9liang@163.com * @Date : 2014/6/22 * @Description :容器的核心接口 */ public interface IContainer{ //获取容器的某个服务提供者实例 public Object getBean(String name); //根据服务提供者名称,服务名称,参数来获取容器提供的服务 //由三者肯定一个惟一的服务。 public Object getService(String beanName,String serviceName,Object... args); //获取容器全部服务描述信息 public IDataContext getBeanDefinitionContext(); //获取容器中某个服务提供者的描述信息 public BeanEntity getBeanDefinition(String name); //获取容器中全部服务提供者实例的缓存 public IDataContext getBeanCacheContext(); //热加载新的服务提供者 public void initContainerService(String resource); }
说明:Container采用外观模式,充当Factory的外观层。Container能够自定义实现,这是扩展点一。并且使用了工厂模式和策略模式实现容器内部具体工厂的动态加载。
(2)Factory接口与默认实现
核心代码:
import com.tgb.Entity.BeanEntity; import com.tgb.data.IDataContext; import com.tgb.handler.HandlerDecorator; import java.io.Serializable; /** * @Author : JiaLin * @Email : shan9liang@163.com * @Date : 2014/6/22 * @Description : 抽象的服务工厂,定义处理服务的算法骨架,具体由其子类实现。 */ //使用模板方法模式定义算法的骨架,具体实现有相应的子类去作。 public abstract class AbstractBeanFactory implements IBeanFactory, Serializable { //----------组件初始化----------begin----- protected IDataContext beanDefinitionContext;//服务描述信息的存储区 protected IDataContext beanCacheContext; //服务提供者实例的缓存区 protected HandlerDecorator handlerDecorator;//转换器(元数据到服务描述信息) //设置服务描述信息的存储区 public abstract void setBeanDefinitionContext(String beanDefinitionContextName, String resource); //设置服务提供者实例的缓存区 public abstract void setBeanCacheContext(String beanCacheContextName); //设置转换器(元数据到服务描述信息) public abstract void setHandler(String defaultHandler, String handlerName); @Override //模板方法 //注册服务组件,初始化服务描述信息 public final void registerBeanDefinition(String resource, String cacheContext, String definitionContext, String defaultHandler, String customHandler) { this.setHandler(defaultHandler, customHandler); this.setBeanCacheContext(cacheContext); this.setBeanDefinitionContext(definitionContext, resource); } //----------组件初始化----------end----- //----------服务提供者的生命周期-----begin-------- //获取某个服务提供者的服务描述信息 public abstract BeanEntity getBeanDefinition(String name); //检查该服务提供者的实例是否有缓存 public abstract boolean containsBeanCache(String name); //从缓存中获取服务提供者的实例 public abstract Object getBeanCache(String name); //建立服务提供者 public abstract Object creatBean(BeanEntity beanEntity); //将服务提供者实例注册到缓存 public abstract Object regiterBeanCache(String name, Object obj); //----------服务提供者的生命周期-----end-------- @Override //模板方法 //获取服务提供者实例 public final Object getBean(String name) { //获取某个Bean的定义 BeanEntity beanEntity = getBeanDefinition(name); //判断这个Bean是否已经加载到缓存,若是有,直接返回 if (containsBeanCache(name)) { return getBeanCache(name); } //建立bean的实例 Object beanObject = this.creatBean(beanEntity); //注册到缓存 regiterBeanCache(name, beanObject); //返回bean的实例 return beanObject; } //获取全部的服务描述信息 public abstract IDataContext getBeanDefinitionContext(); //获取全部的服务实例缓存信息 public abstract IDataContext getBeanCacheContext(); }
说明:AbstractBeanFactory采用模板方法模式,AbstractBeanFactory中定义了初始化服务定义信息和获取服务提供者实例两个模板方法,定义了算法的骨架。模板方法依赖的方法的实现交给子类去完成,这里交给DefaultBeanFactory完成。能够实现本身的BeanFactory,这是扩展点二。
(3)DataContext的接口及实现
核心代码:
import java.util.Map; /** * @Author : JiaLin * @Email : shan9liang@163.com * @Date : 2014/6/22 * @Description :抽象的数据存储接口 */ public interface IDataContext { public void initData(Map<String,Object> map); public void set(String name,Object obj); public Object get(String name); public Map<String,Object> getAll(); }
说明:IDataContext定义了存储区域应该有的方法,两个实现,DefaultBeanDefinitionContext是服务提供者描述信息存储的默认实现;DefaultBeanCacheContext是服务提供者实例存储的默认实现。能够自定义存储区实现,这是扩展点三。
(4)Handler接口及实现
核心代码:
import java.util.Map; /** * @Author : JiaLin * @Email : shan9liang@163.com * @Date : 2014/6/23 * @Description : 抽象的处理器装饰者 */ //使用装饰者模式,能够动态添加功能(这里是动态添加元数据处理器) //例如要扩展Annotation就须要本身扩展处理器,或者扩展xml处理器等等 public abstract class HandlerDecorator implements IHandler{ protected IHandler handler; public void setHandler(IHandler handler){ this.handler=handler; } @Override public Map<String, Object> convert(String string) { if(handler!=null) { return handler.convert(string); } return null; } }
说明:这里采用了一个装饰者模式,默认提供了一个注解装饰者DefaultAnnotationHandler,来把元数据中注解信息转换为服务提供者定义信息。其余开发者可继承HandlerDecorator,来实现本身的装饰者,例如把xml信息转换为服务提供者定义信息的Xmlhandler。工厂会依次实现这些装饰者解析元数据。这是扩展点四。
(5)Annotation
核心代码:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Author : JiaLin * @Email : shan9liang@163.com * @Date : 2014/6/22 * @Description :用来标注服务的提供者 */ @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.FIELD, ElementType.TYPE }) public @interface Bean { String name(); }
说明:这里提供了三个注解来描述服务提供者的元数据,handler据此将元数据转换为服务提供者定义信息。其余开发者可扩展该Annotation,实现本身的Annotation,而后自定义解析的handler,重写factory的createBean方法便可。这是扩展点五。
(5)定义数据结构,存储服务定义信息
import java.util.List; /** * @Author : JiaLin * @Email : shan9liang@163.com * @Date : 2014/6/22 * @Description :服务提供者描述信息载体,其数据结构以下: * * BeanEntity * * name type List * @bean注解名 Bean类型 ServicEntity的arrayList * ServiceEntity…… * * name value List * @Service注解名 方法名 ParamEntity的ArrayList * ParamEntity…… * name value * @param注解名 参数类型 */ public class BeanEntity { private String name; //服务提供者名 private String type; //服务提供者实例的类型 private Object value; //服务提供者实例 private List<ServiceEntity> serviceEntityList; //服务提供者提供的全部服务 public BeanEntity(){} public BeanEntity(String name,String type) { this.name=name; this.type=type; } //省略get,set方法 }
说明:这是java反射的工具类,封装了一些反射经常使用方法。
(7)热加载监听器
说明:这个监听器,将监听某个位置,若是加入新的服务提供者元数据,将被容器热加载。
3、全部代码
一、上面介绍了需求,设计,以及核心代码,若是依然不过瘾,那来看看所有代码吧。
我已将这个小项目开源,托管到CSDN CODE 公有项目,项目首页:
https://code.csdn.net/shan9liang/ioccontainer
二、你们能够帮着改进,也能够下载查看,还有不少改进的地方,最近工做繁忙,有空会持续更新,欢迎提出宝贵意见。