spring中的工厂FactoryBean

Posted

tags:

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

工厂bean是Spring中的特殊Bean,工厂bean必须要实现FactoryBean接口。FaCtoryBean接口是工厂Bean的标准接口。Factorybean提供以下三个方法,

T getObject():实现该方法负责返回该工厂Bean生成的Java实例。

Class<?> getObjectType():实现该方法返回该工厂Bean生成的Java实例的实现类

boolean isSingleton():实现该方法表示工厂Bean生成的java实例是否是单利模式的。 

程序通过getBean()方法获取工厂bean时,并不返回工厂bean的实例,而是获取getObject()中返回的实例。

下面看一个例子:

package com.spring.test.factorybean;
import java.lang.reflect.Method;
import org.springframework.beans.factory.FactoryBean;

public class MyFactorybean implements FactoryBean<Object>{
    private String name;
    public MyFactorybean(){
        System.out.println("beanFactory被调用");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Object getObject() throws Exception{
        if(("apple").equals(name)){
            Class<?> clazz=Class.forName("com.spring.test.factorybean.iPhone");
            
            Object obj= clazz.newInstance();
             Method method = obj.getClass().getMethod("setMsg", String.class);
             method.invoke(obj, "iphone5s");
             return obj;
             
        }else{
            Class<?> clazz=Class.forName("com.spring.test.factorybean.MIPhone");
            Object obj= clazz.newInstance();
             Method method = obj.getClass().getMethod("setMsg", String.class);
             method.invoke(obj, "MI5");
             return obj;
        }    
    }
    public Class<?extends Object>getObjectType(){
        return Object.class;
    }
    public boolean isSingleton(){
        return false;
    }

    
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="apple" class="com.spring.test.factorybean.MyFactorybean">
        <property name="name" value="apple"/>
    </bean>
    <bean id="xiaomi" class="com.spring.test.factorybean.MyFactorybean">
        <property name="name" value="xiaomi"/>
    </bean>
    
</beans>

运行结果为

技术分享

每次配置bean之后都会调用factorybean的构造函数,但是构造函数中并没有返回实例。实例是在getObject的方法中被调用的。

Spring还提供了一些公有的bean,较为常见的有:

PropertyPathFactoryBean:调用getter()方法;

FieldRetreiecingFactoryBean:调用类对象的属性值;

MethodInvokingFactoryBean:调用普通方法;

(一)PropertyPathFactoryBean

PropertyPathFactoryBean获取目标bean的getter()方法注入给其他bean,也可以直接定义成新的bean。在使用PropertyPathFactoryBean调用其他的bean的时候,需要使用

SetTargetObject(Object targetObject)指定需要调用的对象。使用setPropertyPath(String propertyPath)方法指定调用哪个getter()方法。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="apple" 
    class="com.spring.test.factorybean.iPhone">
        <property name="msg" value="iphone6"/>
    </bean>
    
    <bean id="msg" 
    class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
        <property name="targetBeanName" value="apple"/>
        <property name="propertyPath" value="msg"/>
    </bean>

</beans>

运行结果为

技术分享

msg的值为apple对象的getMsg()方法的返回值,也可以将获取getter()方法的值注入到其他的bean中例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="apple" 
    class="com.spring.test.factorybean.iPhone">
        <property name="msg" value="iphone6"/>
    </bean>
    
    <!-- <bean id="msg" 
    class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
        <property name="targetBeanName" value="apple"/>
        <property name="propertyPath" value="msg"/>
    </bean>-->
    
    <bean id="apple1" 
        class="com.spring.test.factorybean.iPhone">
        <property name="msg">
            <bean id="apple.msg" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
        </property>
    </bean>

</beans>
package com.spring.test.factorybean;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testmain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ApplicationContext ctx=new ClassPathXmlApplicationContext("PropertyPathFactoryean.xml");
        Phone p1=(iPhone)ctx.getBean("apple");
        Phone p2=(iPhone)ctx.getBean("apple1");
        
        p2.call();

    }

}
技术分享

从上面的例子可以看出,p2的msg属性是由p1的getMsg()方法的值注入的。

(二)FieldRetrievingFactroybean

FieldRetrievingFactroybean可以访问类的静态属性或实例属性(实例属性大多封装可已使用PropertyPathFactoryBean代替,所以此用处不多)。这里只介绍访问静态Field。

需要使用SetTargetClass(String targetClass)指定需要调用的类。使用setTargetField(String targetField)方法指定访问的类静态属性。用法与上述代码相似这里就不一一举例了。FieldRetrievingFactroybean 还提供了setStaticFField(String staticField)方法可一直接调用类的静态属性。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="apple" 
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
        <property name="staticField" value="apple.msg"/>
    </bean>

</beans>

以上是关于spring中的工厂FactoryBean的主要内容,如果未能解决你的问题,请参考以下文章

Spring中Bean的配置方式之FactoryBean

spring注解第05课 FactoryBean

Spring5学习笔记 — “工厂Bean(FactoryBean)”

《Spring揭秘》---- 工厂方法与FactoryBean

Spring配置bean的方法(工厂方法和Factorybean)

Spring 中 BeanFactory 与 FactoryBean 的区别