阿豪说Spring之开篇BeanFactory

阿豪说Spring之开篇BeanFactory
阿豪说Spring之开篇BeanFactory

写在前面

想来从开始接触和使用Spring已四年有余,虽说使用不成问题,但对其内部具体实现实现原理却只知一二,于是乎痛下决心要好好撸一遍Spring,以便更好地使用Spring的高级功能而且还能知其然知其所以然,吸收它的好思想、设计模式等等,从现在开始每次把get到的相关内容跟各位客官分享,愿一起进步,一起走的更远!除了Spring,后续我们也尝试着撸Mybatis等框架,以求功力大增。

Spring基石

BeanFactory,毫无疑问,就是生产Bean的工厂。我们都知道Spring框架提倡我们使用POJO,如果我们把每个业务对象都看成是一个JavaBean的话,我们就能很好的理解这个名字的由来了。Spring中生产Bean的过程并没有想象中的简单,这个工厂至少还应该具有业务对象的注册以及对象间依赖关系绑定等功能,这样看起来才是一个完整的工厂。

我们都知道苹果公司将自己生产的或者从别的供应商那里采购的手机零件输送到富士康工厂,那就可以在富士康生产线的最后一个节点获取成品的苹果手机。如果我们可以把BeanFactory看作是富士康厂,那手机配件就是各个业务对象。也就是说我们可以直接从BeanFactory中获取已经组装好的所需对象,而不需要关心该对象到底是如何被组装出来的。

对于我们这些使用框架的来说,使用BeanFactory其实很简单,因为它已经提供了取得组装完成的对象的方法,源码如下:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

这些方法大多都是查询业务对象的,如查找某个对象是否存在的方法(containsBean),获取某个对象的方法(getBean),当然由于需要存在诸多的重载方法。

BeanFactory提供的便利

在BeanFactory没有出现之前,我们如果需要某个类的对象毫无疑问是直接new一个,出来,那现在只需要将这些工作让BeanFactory来干就好了,具体实例如下:

AClass a = new AClass();
BClass b = new BClass();
CClass c = new CClass();
a.setB(b);
a.setC(c);
a.doSomeThing();

有了BeanFactory之后,我们需要画出一个生产图纸并告诉它就可以了,如下:

<beans>
    <bean id="a" class="AClass">
        <property name="b" ref="b"/>
        <property name="c" ref="c"/>
  </bean>
  <bean id="b" class="BClass"></bean>
  <bean id="c" class="CClass"></bean>
</beans>

然后我们可以如下调用:

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("上面配置文件位置"));
AClass a = (AClass)factory.getBean("a");
a.doSomeThing();

乍看起来好像改变并不是很大对不对?没关系看官别急,随着学习的深入我们会慢慢的能体会到其中的奥秘。

BeanFactory如何维护Bean关系

实际上,BeanFactory并不负责直接维护Bean关系,而是将Bean之间的关系委托给BeanDefinitionRegistry来进行管理。在Spring中,每一个Bean的原信息都会被看做是一个BeanDefinition,也就是Bean定义。那BeanDefinitionRegistry通过管理这些BeanDefinition从而实现对Bean的关系。我们可以把BeanDefinition看做是图书馆里的一本书,而BeanDefinitionRegistry就是图书馆的书架。从上文源码中我们得知BeanFactory其实是个接口,那它的功能终究是会由它的实现类来完成,DefaultListableBeanFactory就是这个一个实现类。这几个概念之间的UML类图如下:
阿豪说Spring之开篇BeanFactory

在BeanFactory中,每一个交给它管理的对象,在BeanDefinitionRegistry中都会有一个BeanDefinition实例跟关联对象绑定,BeanDefinition实例负责保存该Bean的原信息,如class类型、构造方法参数等。当我们向BeanFactory索要bean时,它就根据这些原信息生成一个可用的对象给到我们。

透过BeanFactory看Spring

通过上面的内容,我们不难发现,对于Spring来说,在初始化阶段要首先完成三件事:收集Bean原信息、注册Bean原信息、根据原信息生成Bean代理对象,只有这样才能很好为我们服务。收集时可以通过XML文件收集、可以通过TXT文件收集、可以通过代码(包括通过注解和手动调用收集方法)收集。注册就是将收集到Bean原信息保存到BeanDefinitionRegistry中以便后续使用。

阿豪说Spring之开篇BeanFactory

阿豪说
学到了?请我喝杯咖啡吧~

上一篇:哈尔滨黑龙江上海深圳厦门


下一篇:Spring七大模块