[源码系列:手写spring] IOC第十二节:FactoryBean

内容介绍

        在 Spring 框架中,FactoryBean 是一个特殊的工厂类接口,用于创建和管理复杂的 bean 对象。它允许你自定义 bean 的创建逻辑,并且可以在 bean 创建过程中执行一些额外的操作。FactoryBean 接口通常用于创建那些非常复杂或需要特殊处理的 bean 实例,例如连接池、远程服务代理等。

        当我们向容器中获取FactoryBean时,容器返回的不是他本身,而是他的getObject()方法的返回值。

FactoryBean 接口有两个核心方法:

  1. T getObject():该方法负责创建和返回一个 bean 实例。你可以在这个方法中编写自定义的 bean 创建逻辑。

  2. Class<?> getObjectType():该方法返回工厂创建的 bean 的类型。通常,它用于告诉 Spring 容器工厂创建的 bean 类型是什么。

代码分支

https://github.com/yihuiaa/little-spring/tree/factory-beanicon-default.png?t=N7T8https://github.com/yihuiaa/little-spring/tree/factory-bean

核心代码

 FactoryBean接口

public interface FactoryBean<T> {

	T getObject() throws Exception;

	boolean isSingleton();
}

  AbstractBeanFactory

         在getBean方法中添加BeanFactory的逻辑,当bean属于BeanFactory类型的,就拿他的getObject方法返回的对象,并根据isSingleton()方法返回时决定是否加入缓存。

....
用于缓存单例的BeanFactory提供类
private final Map<String, Object> factoryBeanObjectCache = new HashMap<>();



private Object getObjectForBeanInstance(Object sharedInstance, String beanName) throws Exception {
        Object obj = sharedInstance;
        if(sharedInstance instanceof FactoryBean){
            try {
                FactoryBean factoryBean = (FactoryBean<?>)sharedInstance;
                if(((FactoryBean<?>)sharedInstance).isSingleton()){
                    //singleton作用域bean,从缓存中获取
                    obj = this.factoryBeanObjectCache.get(beanName);
                    if( obj == null ){
                        obj  =  factoryBean.getObject();
                        this.factoryBeanObjectCache.put(beanName, obj);
                    }
                }else{
                    //prototype作用域bean,新创建bean
                    obj  =  factoryBean.getObject();
                }
            }catch (Exception e){
                throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", e);
            }
        }
        return obj;
    }

....

        

测试

xml

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

    <bean id="person" class="bean.PersonFactoryBean">
        <property name="name" value="yiHuiGoGoGO"/>
    </bean>

</beans>

FactoryBean

public class PersonFactoryBean implements FactoryBean<Person> {
    private  String name;

    @Override public Person getObject()  {
        Person person = new Person();
        person.setName("YiHuiComeOn");
        person.setAge("18");
        return person;
    }
    @Override public boolean isSingleton() {
        return true;
    }
....

测试类

	@Test
	public void testFactoryBean(){
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:factory-bean.xml");
		Person person = applicationContext.getBean("person", Person.class);
		System.out.println(person);
	}

测试结果

输出的确实是getObject返回的类,而不是类本身。

Person{name='YiHuiComeOn', age='18', car=null}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值