FactoryBean接口

Bean可以继承此接口。
getBean的时候,BeanName如果以 &开头,就直接返回此Bean
如果不是,就返回 getObject()

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

继承了此接口的Bean,在getBean时有特殊处理,流程如下:

app.getBean("FactoryBeanName");app.getBean("&FactoryBeanName");

	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		// 分析 .getBean(name)
		return getBeanFactory().getBean(name);
	}

AbstractBeanFactory.getBean();

    public Object getBean(String name) throws BeansException {
    	// 分析 doGetBean
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

AbstractBeanFactory.doGetBean();

    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            // ...
            // 分析 getObjectForBeanInstance
            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else // ... 当然 else 中也有 getObjectForBeanInstance
   }

AbstractBeanFactory.getObjectForBeanInstance();

    public static boolean isFactoryDereference(@Nullable String name) {
    	// 判断 BeanName 是否以 & 开头
        return name != null && name.startsWith("&");
    }
    
    protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    	// isFactoryDereference 在上面
        if (BeanFactoryUtils.isFactoryDereference(name)) { // 如果beanName以 & 开头,直接返回Bean
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            } else if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            } else {
                if (mbd != null) {
                    mbd.isFactoryBean = true;
                }

                return beanInstance;
            }
        } else if (!(beanInstance instanceof FactoryBean)) { // 如果没有继承FactoryBean,直接返回
            return beanInstance;
        } else { // 继承了FactoryBean,BeanName不以 & 开头
            // ...
            if (object == null) {
                // ...
                // 分析 getObjectFromFactoryBean
                object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
            }

            return object;
        }
    }

FactoryBeanRegistrySupport.getObjectFromFactoryBean();

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        if (factory.isSingleton() && this.containsSingleton(beanName)) {
			// ...
        } else {
            // 分析 doGetObjectFromFactoryBean
            Object object = this.doGetObjectFromFactoryBean(factory, beanName);
            // ...
            return object;
        }
    }
    
    private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
        Object object;
        try {
            if (System.getSecurityManager() != null) {
               // ...
            } else {
            	// 这行代码眼熟吧,就是FactoryBean接口里用来返回对象的。
                object = factory.getObject();
            }
        } // ...
        return object;
    }

通过 factory.getObject()获取真实对象,如果BeanName用 &开头,就直接返回那个 FeactoryBean。

posted @ 2020-11-15 14:29  qianbuhan  阅读(130)  评论(0)    收藏  举报