欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

FactoryBean

程序员文章站 2022-05-23 18:10:44
...

一、只谈FactoryBean,不谈BeanFactory

众所周知,Spring容器管理着其内部的Bean,在这些Bean中可能存在着一类特殊的Bean,这一类特殊的Bean就是FactoryBean

FactoryBean与其它的Bean不一样的地方在于它能生产Bean

另外,从容器中获取它和它产生的Bean的方式有些特殊。

二、为什么使用FactoryBean?

一般情况下,Spring通过反射机制,利用< bean>中的class属性指定的实现类实例化Bean。

在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,需要在< bean>中提供大量的配置信息。配置方法的灵活性受限,这时采用编码方式可能会得到一个简单的方案。

Spring为此提供了一个org.springframework.beans.factory.FactoryBean工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。可以隐藏实例化一些复杂Bean的细节。给上层应用带来便利。

从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean< T>的形式

以Bean结尾,表示他是一个Bean,不同于其他bean的是:它实现了FactoryBean< T>的接口。该Bean的ID实际上是从BeanFactory中获取的实际的getObject()返回的对象,而不是FactoryBean本身。如果要获取FactoryBean对象,可以在id前面加一个&符号来获取。

三、FactoryBean是什么?

package org.springframework.beans.factory;

import org.springframework.lang.Nullable;

public interface FactoryBean<T> {

	/**
	* 返回由FactoryBean创建bean的实例,如果是单例模式(isSingleton=true)则该实例会放在Spring容器单例的缓存池中。
	*/
	@Nullable
	T getObject() throws Exception;

	/**
	* 返回FactoryBean创建的Bean实例
	*/
	@Nullable
	Class<?> getObjectType();

	/**
	* 返回由FactoryBean创建的实例是不是单例
	*/
	default boolean isSingleton() {
		return true;
	}

}

四、FactoryBean怎么用?

在使用之前再次强调,我们为什么要用FactoryBean?

FactoryBean通常是用来创建比较复杂的Bean,一般的bean使用XML配置即可,但若是一个Bean的创建过程中涉及到很多其他Bean 和 复杂的逻辑,使用XML配置比较复杂的话,这时可以考虑使用FactoryBean

MyFactoryBean

/*
 * Copyright (C), 2013-2019, 天津大海云科技有限公司
 */
package com.jikang.config;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

import java.util.Arrays;
import java.util.List;

/**
 * @author yangjikang
 * @date 2019/8/28 10:40
 * @modified By yangjikang
 * @since
 */
public class MyFactoryBean implements FactoryBean<List<String>>, InitializingBean, DisposableBean {

    private String params = "";

    private List<String> list;

    @Override
    public List<String> getObject() throws Exception {
        return list;
    }

    @Override
    public Class<?> getObjectType() {
        return List.class;
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("对象销毁...");
    }

    /**
     *  InitializingBean实现方法
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        //属性注入完后,调用该方法,该方法可以实现“业务”逻辑。创建出List<String>集合
        String[] split = params.split(",");
        list = Arrays.asList(split);
    }

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }
}

application.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="myList" class="com.jikang.config.MyFactoryBean">
        <property name="params" value="1,2,3,4"/>
    </bean>
    
</beans>

App

/*
 * Copyright (C), 2013-2019, 天津大海云科技有限公司
 */
package com.jikang;

import com.jikang.config.MyFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;

/**
 * @author yangjikang
 * @date 2019/8/26 17:09
 * @modified By yangjikang
 * @since
 */
public class App {
    public static void main(String[] args) throws Exception{
        // 用我们的配置文件来启动一个 ApplicationContext
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

        System.out.println("context 启动成功");

        // 从 context 中取出我们的 MyFactoryBean
        MyFactoryBean myFactoryBean = (MyFactoryBean) context.getBean("&myList");
        System.out.println("通过&获取MyFactoryBean:"+myFactoryBean);

        // 从 context 中取出我们的 ArrayList
        List list = (List) context.getBean("myList");
        System.out.println("MyFactoryBean实际返回的是:"+list);

        //通过MyFactoryBean对象的getObject()方法获取对象
        List<String> getListFormMyFactoryBean = myFactoryBean.getObject();
        System.out.println("通过MyFactoryBean#getObject()获取的对象信息:"+getListFormMyFactoryBean);

        //通过MyFactoryBean对象的getObjectType()方法获取类信息
        Class getClassFormMyFactoryBean = myFactoryBean.getObjectType();
        System.out.println("通过MyFactoryBean#getObjectType()获取的类信息:"+getClassFormMyFactoryBean);

        //销毁
        myFactoryBean.destroy();
    }
}

控制台
FactoryBean

相关标签: FactoryBean