Spring源码解析-FactoryBean

643 阅读2分钟

如果一个对象实现了BeanFactory它本身就是一个工厂,BeanFactory.getBean返回的一个对象,不是原来对象的本身,而是原来对象的代理对象。

FactoryBeans 可以支持单例和原型,并且可以要么根据需要懒惰地创建对象,要么在启动时急切地创建对象。 {@link SmartFactoryBean} 接口允许暴露更细粒度的行为元数据。

FactoryBean它是一个bean,但是它是一个特殊的Bean是工厂。 FactoryBean本身它所创建出来的对象并不是FactoryBean这个实例本身,而是由这个FactoryBean工厂所创建出来的对象。

FactoryBean这个接口在框架本身内被大量使用,因为AOP的示例{@linkorg.springframework.aop.framework.ProxyFactoryBean}或 {@linkorg.springframework.jndi.JndiObjectFactoryBean}。 它也可以用于应用程序组件;然而这在基础设施代码之外并不常见。

BeanFactory和FactoryBean的区别:

  • BeanFactory它是整个Spring容器的一个根容器它里面描述了在所有的子接口或者子类当中对于容器的一些处理原则,职责到底是什么,生命周期的一些方法的约定。
  • FactoryBean本身是存活在BeanFactory当中的它本身也是一个工厂,这个工厂的作用是用于创建由FactoryBean所能创建的对象,在创建出来的这个对象的前面或者后面时候,可以额外执行一些方法,来实现AOP。

BeanFactory返回对象的方法

<T> T getBean(Class<T> requiredType) BeanFactory根据类型获取一个对象,如果该类型存在多个对象,那么它是如何确定返回唯一的一个对象。这里的唯一指的是,当用指定类型的方式获取spring容器中bean对象时,spring容器中的那个类型的bean只能声明一个!而不是说你只能写一次getBean(Book.class)的意思,你可以写很多很多个,当你没声明scope是多例的时候,你声明再多个也只是给你同一个对象。

举例说明 当我spring容器中声明了两个同样类型而id不同bean实例person1与person2时

<bean id="person1" class="com.test.pojo.Person" scope="prototype">
    <property name="name" value="Zhangsan"/>
    <property name="pet" ref="pet"/>
</bean>

<bean id="person2" class="com.test.pojo.Person" scope="prototype">
    <property name="name" value="Zhangsan"/>
    <property name="pet" ref="pet"/>
</bean>

这种情况,只能用id或者id与类型的方式来获取bean对象,因为存在两个或多个类型相同的bean对象时,你用获取类型的方式来获取bean对象,spring容器并不知道你需要的是哪一个,所以会报错。

public void test2(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person1 = context.getBean(Person.class);
    System.out.println(person1);
    //如果spring容器中只有唯一的person类型bean的话,这么写是没毛病的
    Person person2 = context.getBean(Person.class);
    System.out.println(person2);
    //id方式获取
    Person person3 = (Person) context.getBean("person1");
    System.out.println(person3);
}

No qualifying bean of type ‘com.test.pojo.Person’ available: expected single matching bean but found 2: person1,person2 翻译过来就是找到了两个都是person类型不知大你要用哪一个。所以需要用Object getBean(String name)或者 T getBean(String name,Class requiredType)。

<T> T getBean(Class<T> requiredType, Object... args) throws BeansException; 返回一个覆盖原来设置参数的bean