spring 之 factory-bean & factory-method

Posted 10年 Java程序员,硬核人生!勇往直前,永不退缩!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring 之 factory-bean & factory-method相关的知识,希望对你有一定的参考价值。

这两者常常是一起出现的,或者说他们经常是一起被使用的。但是其实是分为了两种情况:

1 同时使用factory-bean 和 factory-method

如果,我们在一个bean 元素上同时配置 factory-bean 和 factory-method, 那么意思就是说, 这个bean 的创建就使用工厂模式吧, 工厂模式的创建者, 也就是主体bean 是 factory-method 指向的 bean, 而 工厂方法呢? 就是 factory-method。  不过呢, 这里有个要求, 工厂类的  factory-method 方法必须是非静态的, 而且必须要返回 当前bean 的实例对象。 但是它可以是 private 方法。

 

这个其实很好理解:

factory-method 方法必须是非静态的—— 如果是静态的,那么我们就不需要多此一举引用factory-bean 的实例了吧, 再就是static工厂方法,也不需要spring 来管理了吧! 直接 XxxFactory.getYyy(), 这样的方式不就好了吗?  

如果是静态的,则出现异常:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name boss defined in class path resource [beans.xml]: No matching factory method found: factory bean man; factory method fmm(String). Check that a method with the specified name and arguments exists and that it is non-static.
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:549)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1134)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1028)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
    at AnnoIoCTest.main(AnnoIoCTest.java:9)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

 

必须要返回 当前bean 的实例对象—— 如果不是返回 一个bean实例, 那还算是哪门子的 工厂方法?

 

还有, 如果我们在一个bean 元素上同时配置 factory-bean 和 factory-method,那么bean的 class 属性是可以省去的, 那么bean 的类型呢? factory-method 返回什么就是什么, 返回 String, int  也是可以的!

 

另外, 工厂方法是可以有参数的, 如果有参数,那么 我们需要通过  bean 元素的 子元素 constructor-arg 进行配置。原理跟 普通的 构造方法注入是一样的。 不过呢, 这个constructor-arg 是 factory-bean 进行调用 以及注入的, 不是spring  IoC 注入的。

    <bean id="boss"  init-method="initBoss" lazy-init="true" destroy-method="destro"
          factory-method="fmm"
          factory-bean="man"
    >
        <constructor-arg value="6"></constructor-arg>
    </bean>

    <bean id="man" class="com.baobaotao.Man" dependency-check="none"  scope="prototype"  lazy-init="true"/>

 

 

2 单独使用 当前类的静态方法: factory-method 。 也就是只配置了 factory-method, 没有配置  factory-bean 

这两种情况是很大差别的!!

如果单独使用  factory-method, 那么这个 factory-method 必须是 当前class 的静态方法。 试想, 如果不是静态方法,又要使用工厂方法, 又要通过spring 来创建bean, 那么就 太矛盾了吧! 

 

前面我们说 “ 直接 XxxFactory.getYyy(), 这样的方式不就好了吗”,其实这个说法也是不太准确的。  那么 这个时候,通过单独使用  factory-method 静态方法的意义呢?  我想, 大概在于我们可以给 静态 工厂方法注入一些 参数, 以用来构造 我们的bean 吧!  这个正是spring 的灵活之处。

 

以上是关于spring 之 factory-bean & factory-method的主要内容,如果未能解决你的问题,请参考以下文章

Spring错误——Spring 注解——factory-bean reference points back to the same bean definition

Spring中bean的parent、depends-on、factory-bean、factory-method属性

spring的三种实例化方式

Spring 一二事 - 别名

Spring6| Bean的四种获取方式(实例化)

Spring-IOC学习笔记-05bean的属性