在构建Tiny框架之初,想着是不是不要强依赖Spring?于是就写了一个类Spring的依赖注入容器,基本实现了Spring的依赖注入部分的功能,工作情况也良好,配置规范也是采用的Spring的规范。在前面一直是没有问题的,但是在做数据库业务的时候,出现问题了。做数据库,必须要考虑事务问题,而当时我的设计目标是对各种开源的ORMapping方案都不拒绝,这个时候就引入一个问题,要么自己再实现一套AOP,要么就复用Spring。当时预想的另外一个方案是核心框架采用非直接依赖Spring的方案,数据库相关的采用Spring依赖的方式。但是实际上,业务层面的Bean会依赖系统层面的Bean,这又涉及到两个容器之间的协作,这个时候,我意识到,是应该做一个取舍了。
所以果断放弃自己来做IOC和AOP方面的工作,而采用强依赖Spring来实现的方案,毕竟在现在的应用场景下,拒绝Spring就等于让别人拒绝自己。
但是,不管怎么样,在实现这个容器的过程中,还是让我对依赖注入方面有了更深的了解,因此,这两天的投入还是值得的。
下面展示一下,它实现的功能:
<beans> <bean id="user" name="user,user1,user2" scope="singleton" class="org.tinygroup.factory.config.User"> <property name="name"> <value>aa</value> </property> <property name="age"> <value>12</value> </property> <property name="cat"> <ref id="cat" /> </property> <property name="cats"> <list> <ref id="cat" /> </list> </property> <property name="catSet"> <list> <ref id="cat" /> </list> </property> <property name="catMap"> <map> <entry key="aa" value-ref="cat"></entry> </map> </property> </bean> <bean id="cat" scope="singleton" class="org.tinygroup.factory.config.Cat" /> <bean id="cat1" scope="prototype" class="org.tinygroup.factory.config.Cat" /> <bean id="aaa1" scope="singleton" class="org.tinygroup.factory.config.Aaa"> <property name="name"> <value>aaa1</value> </property> </bean> <bean id="aaa" scope="singleton" class="org.tinygroup.factory.config.Aaa"> <property name="name"> <value>aaa</value> </property> </bean> <bean id="bbb" scope="singleton" class="org.tinygroup.factory.config.Bbb" autowire="byType" /> <bean id="ccc" scope="singleton" class="org.tinygroup.factory.config.Ccc" autowire="byName" /> <bean id="user2" name="user,user1,user2" scope="prototype" class="org.tinygroup.factory.config.User"> <property name="name"> <value>aa1</value> </property> <property name="age"> <value>121</value> </property> <property name="cat"> <ref id="cat1" /> </property> </bean> </beans>可以看到,配置与Spring是兼容的。
下面是一些测试用例:
public void testAutoAssemble() { assertNotNull(factory.getBean("aaa")); Bbb bbb = factory.getBean("bbb"); assertEquals("aaa", bbb.getAaa().getName()); bbb = factory.getBean("bbb"); assertEquals("aaa", bbb.getAaa().getName()); Ccc ccc = factory.getBean("ccc"); assertEquals("aaa1", ccc.getAaa1().getName()); ccc = factory.getBean("ccc"); assertEquals("aaa1", ccc.getAaa1().getName()); } public void testInitComparePrototype() { Cat cat = factory.getBean("cat1"); Cat cat1 = factory.getBean("cat1"); assertEquals(false, cat == cat1); } public void testInitComparePrototype1() { User user = factory.getBean("user2"); User user2 = factory.getBean("user2"); assertEquals(false, user == user2); assertEquals(false, user.getCatMap() == user2.getCat()); }小结:确实,现在要脱离Spring自己再实现一个容器,越来越不合适了,毕竟Spring的用户群在那里,大家都已经熟悉适用的东西,不管是从学习成本各方面都不会选择一个新东西。
OK,虽然是一个失败的实践,但是自己实现与看Spring源码的差别还是有的,就当是一次学习吧。当然,如果是在嵌入式系统或者受限制使用的环境中,只想使用IoC,还是有用处的,毕竟 20K大小的容量还是相当诱人的。