如何实现一个萌芽版的Spring容器
导读:本文共4450.5字符,通常情况下阅读需要15分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 从什么是IOC开始?Spring--春天,Java编程世界的春天是由一位音乐家--Rod Johnson带来的。Rod Johnson先后编写了两本巨著《Expert One-on-One J2EE Design and Development》、《Expert One-on-One J2EE Development without EJB》,拉起了挑战正统Ja... ...
目录
(为您整理了一些要点),点击可以直达。从什么是IOC开始?
Spring--春天,Java编程世界的春天是由一位音乐家--Rod Johnson带来的。
Rod Johnson先后编写了两本巨著《Expert One-on-One J2EE Design and Development》、《Expert One-on-One J2EE Development without EJB》,拉起了挑战正统Java EE框架EJB的大旗。
Rod Johnson不仅是一名旗手,更是开发了Spring这一轻量级框架,像一名勇敢的龙骑兵一样,对EJB发动了冲锋,并最终战胜了EJB,让Spring成为Java EE事实上的标准。
Spring的两大内核分别是IOC和AOP,其中最最核心的是IOC。
所谓的IOC(控制反转):就是由容器来负责控制对象的生命周期和对象间的关系。以前是我们想要什么,就自己创建什么,现在是我们需要什么,容器就给我们送来什么。
也就是说,控制对象生命周期的不再是引用它的对象,而是容器。对具体对象,以前是它控制其它对象,现在所有对象都被容器控制,所以这就叫控制反转。
也许你还听到另外一个概念DI(依赖注入),它指的是容器在实例化对象的时候把它依赖的类注入给它,我们也可以认为,DI是IOC的补充和实现。
工厂和Spring容器
Spring是一个成熟的框架,为了满足扩展性、实现各种功能,所以它的实现如同枝节交错的大树一样,现在让我们把视线从Spring本身移开,来看看一个萌芽版的Spring容器怎么实现。
Spring的IOC本质就是一个大工厂,我们想想一个工厂是怎么运行的呢?
生产产品:一个工厂最核心的功能就是生产产品。在Spring里,不用Bean自己来实例化,而是交给Spring,应该怎么实现呢?——答案毫无疑问,反射。
那么这个厂子的生产管理是怎么做的?你应该也知道——工厂模式。
库存产品:工厂一般都是有库房的,用来库存产品,毕竟生产的产品不能立马就拉走。Spring我们都知道是一个容器,这个容器里存的就是对象,不能每次来取对象,都得现场来反射创建对象,得把创建出的对象存起来。
订单处理:还有最重要的一点,工厂根据什么来提供产品呢?订单。这些订单可能五花八门,有线上签签的、有到工厂签的、还有工厂销售上门签的……最后经过处理,指导工厂的出货。
在Spring里,也有这样的订单,它就是我们bean的定义和依赖关系,可以是xml形式,也可以是我们最熟悉的注解形式。
那对应我们的萌芽版的Spring容器是什么样的呢?
订单:Bean定义
Bean可以通过一个配置文件定义,我们会把它解析成一个类型。
beans.properties
为了偷懒,这里直接用了最方便解析的properties,用一个<key,value>类型的配置来代表Bean的定义,其中key是beanName,value是class
userDao:cn.fighter3.bean.UserDao
BeanDefinition.java
bean定义类,配置文件中bean定义对应的实体
publicclassBeanDefinition{privateStringbeanName;privateClassbeanClass;//省略getter、setter}
获取订单:资源加载
接下订单之后,就要由销售向生产部门交接,让生产部门知道商品的规格、数量之类。
资源加载器,就是来完成这个工作的,由它来完成配置文件中配置的加载。
publicclassResourceLoader{publicstaticMap<String,BeanDefinition>getResource(){Map<String,BeanDefinition>beanDefinitionMap=newHashMap<>(16);Propertiesproperties=newProperties();try{InputStreaminputStream=ResourceLoader.class.getResourceAsStream("/beans.properties");properties.load(inputStream);Iterator<String>it=properties.stringPropertyNames().iterator();while(it.hasNext()){Stringkey=it.next();StringclassName=properties.getProperty(key);BeanDefinitionbeanDefinition=newBeanDefinition();beanDefinition.setBeanName(key);Classclazz=Class.forName(className);beanDefinition.setBeanClass(clazz);beanDefinitionMap.put(key,beanDefinition);}inputStream.close();}catch(IOException|ClassNotFoundExceptione){e.printStackTrace();}returnbeanDefinitionMap;}}
订单分配:Bean注册
对象注册器,这里用于单例bean的缓存,我们大幅简化,默认所有bean都是单例的。可以看到所谓单例注册,也很简单,不过是往HashMap里存对象。
publicclassBeanRegister{//单例Bean缓存privateMap<String,Object>singletonMap=newHashMap<>(32);/***获取单例Bean**@parambeanNamebean名称*@return*/publicObjectgetSingletonBean(StringbeanName){returnsingletonMap.get(beanName);}/***注册单例bean**@parambeanName*@parambean*/publicvoidregisterSingletonBean(StringbeanName,Objectbean){if(singletonMap.containsKey(beanName)){return;}singletonMap.put(beanName,bean);}}
生产车间:对象工厂
好了,到了我们最关键的生产部门了,在工厂里,生产产品的是车间,在IOC容器里,生产对象的是BeanFactory。
对象工厂,我们最核心的一个类,在它初始化的时候,创建了bean注册器,完成了资源的加载。
获取bean的时候,先从单例缓存中取,如果没有取到,就创建并注册一个bean
publicclassBeanFactory{privateMap<String,BeanDefinition>beanDefinitionMap=newHashMap<>();privateBeanRegisterbeanRegister;publicBeanFactory(){//创建bean注册器beanRegister=newBeanRegister();//加载资源this.beanDefinitionMap=newResourceLoader().getResource();}/***获取bean**@parambeanNamebean名称*@return*/publicObjectgetBean(StringbeanName){//从bean缓存中取Objectbean=beanRegister.getSingletonBean(beanName);if(bean!=null){returnbean;}//根据bean定义,创建beanreturncreateBean(beanDefinitionMap.get(beanName));}/***创建Bean**@parambeanDefinitionbean定义*@return*/privateObjectcreateBean(BeanDefinitionbeanDefinition){try{Objectbean=beanDefinition.getBeanClass().newInstance();//缓存beanbeanRegister.registerSingletonBean(beanDefinition.getBeanName(),bean);returnbean;}catch(InstantiationException|IllegalAccessExceptione){e.printStackTrace();}returnnull;}}
生产销售:测试
UserDao.java
我们的Bean类,很简单
publicclassUserDao{publicvoidqueryUserInfo(){System.out.println("Agoodman.");}}
单元测试
publicclassApiTest{@Testpublicvoidtest_BeanFactory(){//1.创建bean工厂(同时完成了加载资源、创建注册单例bean注册器的操作)BeanFactorybeanFactory=newBeanFactory();//2.第一次获取bean(通过反射创建bean,缓存bean)UserDaouserDao1=(UserDao)beanFactory.getBean("userDao");userDao1.queryUserInfo();//3.第二次获取bean(从缓存中获取bean)UserDaouserDao2=(UserDao)beanFactory.getBean("userDao");userDao2.queryUserInfo();}}
运行结果
A good man.
A good man.
至此,我们一个萌芽版的Spring容器就完成了。
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
如何实现一个萌芽版的Spring容器的详细内容,希望对您有所帮助,信息来源于网络。