FactoryBean不来了解下嘛?

670 阅读6分钟

1.FactoryBean定义

Interface to be implemented by objects used within a {@link BeanFactory} which
* are themselves factories for individual objects. If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself

实现该接口的Bean被当做BeanFactory用来产生单个对象,暴露的是产生的对象并不是当前Bean

2.FactoryBean示例

2.1 定义Bean

@Component
public class UserFactoryBean implements FactoryBean<User> {
}

2.2 指定返回对象

@Override
public User getObject() throws Exception {
    return new User();
}

2.3 指定返回类型

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

2.4 完整示例

@Component
public class UserFactoryBean implements FactoryBean<User> {

    @Override
    public User getObject() throws Exception {
        return new User();
    }

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

3.Bean与暴露对象

通常情况下要获取容器中的Bean对象,只需要通过beanFactory.getBean("bean名称")方法即可得到结果,来看看下面的示例

beanFactory.getBean("userFactoryBean");

控制台输出结果:

User(id=null, name=null, age=null)

通过控制台可以看出并非是我们预想的结果,如果想要获取UserFactoryBean,又该怎么做呢?只需要在Bean名称前面添加"&"

beanFactory.getBean("&userFactoryBean");

控制台输出结果:

com.boot.example.factory.UserFactoryBean@5273143e

3.1 实现原理

3.1.1 名称转换

public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    // 如果Bean的名称不是以"&"开头,直接返回
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    // 如果Bean的名称以"&"开头,则进行截取。例如传入Bean的名称为”&userFactoryBean“,处理之后的结果为”userFactoryBean“
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

3.1.2 获取实例

// 根据Bean名称从容器中获取实例
Object sharedInstance = getSingleton(beanName);

3.1.3 获取目标对象

protected Object getObjectForBeanInstance(
   Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // 1.如果Bean名称以”&“开头
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        // 2.直接返回实例对象
        return beanInstance;
    }

    // 3.如果实例对象不是FactoryBean类型直接返回
    if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd != null) {
        mbd.isFactoryBean = true;
    }
    else {
        // 4.从缓存中获取目标对象
        object = getCachedObjectForFactoryBean(beanName);
    }
    // 5.缓存在不存在目标对象
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 6.从FactoryBean中获取目标对象
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

3.1.4调用 FactoryBeangetObject()

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    Object object;
    try {
        if (System.getSecurityManager() != null) {
            AccessControlContext acc = getAccessControlContext();
            try {
                object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        } else {
            // 调用FactoryBean的getObject()方法,得到目标对象
            object = factory.getObject();
        }
    }
    return object;
}

3.1.5 缓存目标对象

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // 调用FactoryBean的getObject()方法,得到目标对象
                object = doGetObjectFromFactoryBean(factory, beanName);
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                } else {
                    if (containsSingleton(beanName)) {
                        // 将目标对象进行缓存,避免重复创建
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
}

3.1.6 总结

  • beanFactory.getBean("&userFactoryBean")从容器中获取Bean对象
  • beanFactory.getBean("userFactoryBean")先从容器中获取Bean对象,调用Bean对象的getObject()方法获取目标对象