海哥 发表于 2023-7-11 09:17:51

spring启动流程 (4) FactoryBean详解

FactoryBean接口

实现类对象将被用作创建Bean实例的工厂,即调用getObject()方法返回的对象才是真正要使用的Bean实例,而不是直接将FactoryBean对象作为暴露的Bean实例。
FactoryBeans可以支持singleton和prototype,并且可以根据需要懒加载或在启动时立即创建对象。
这个接口在编写扫描接口生成代理对象的场景下经常使用,比如Mybatis Mapper接口扫描、Dubbo接口扫描、Feign接口扫描等。
Spring容器只负责管理FactoryBean实例的生命周期,而不是FactoryBean创建的对象的生命周期。因此不会自动调用暴露的Bean对象的destroy方法。FactoryBean应该实现DisposableBean,并将关闭调用委托给底层对象。
public interface FactoryBean<T> {

        /**
       * Return an instance (possibly shared or independent) of the object
       * managed by this factory.
       */
        T getObject() throws Exception;

        /**
       * Return the type of object that this FactoryBean creates,
       * or null if not known in advance.
       */
        Class<?> getObjectType();

        /**
       * Is the object managed by this factory a singleton?
       */
        default boolean isSingleton() {
                return true;
        }
}我们可以使用正常的getBean(beanName)方式获取通过getObject()方法暴露的Bean实例,也可以使用getBean("&" + beanName)方式获取FactoryBean的实例。
下文将介绍其实现方式。
FactoryBean的实现方式

Spring创建单例Bean的逻辑在DefaultListableBeanFactory的preInstantiateSingletons()方法中:
public void preInstantiateSingletons() throws BeansException {

        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                        if (isFactoryBean(beanName)) {
                                // 此处使用"& + beanName"作为beanName创建FactoryBean实例
                                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                                if (bean instanceof FactoryBean) {
                                        FactoryBean<?> factory = (FactoryBean<?>) bean;
                                        boolean isEagerInit;
                                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                                                isEagerInit = AccessController.doPrivileged(
                                                                (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                                                getAccessControlContext());
                                        } else {
                                                isEagerInit = (factory instanceof SmartFactoryBean &&
                                                                ((SmartFactoryBean<?>) factory).isEagerInit());
                                        }
                                        if (isEagerInit) {
                                                getBean(beanName);
                                        }
                                }
                        } else {
                                getBean(beanName);
                        }
                }
        }

        // Trigger post-initialization callback for all applicable beans...
        // ...
}

public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(
                String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly)
                throws BeansException {

        // 此步骤将&符移除
        String beanName = transformedBeanName(name);
        Object bean;

        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else {
                if (isPrototypeCurrentlyInCreation(beanName)) {
                        throw new BeanCurrentlyInCreationException(beanName);
                }

                BeanFactory parentBeanFactory = getParentBeanFactory();
                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                        String nameToLookup = originalBeanName(name);
                        if (parentBeanFactory instanceof AbstractBeanFactory) {
                                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                                                nameToLookup, requiredType, args, typeCheckOnly);
                        } else if (args != null) {
                                return (T) parentBeanFactory.getBean(nameToLookup, args);
                        } else if (requiredType != null) {
                                return parentBeanFactory.getBean(nameToLookup, requiredType);
                        } else {
                                return (T) parentBeanFactory.getBean(nameToLookup);
                        }
                }

                if (!typeCheckOnly) {
                        markBeanAsCreated(beanName);
                }

                try {
                        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                        checkMergedBeanDefinition(mbd, beanName, args);

                        String[] dependsOn = mbd.getDependsOn();
                        if (dependsOn != null) {
                                for (String dep : dependsOn) {
                                        if (isDependent(beanName, dep)) {
                                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                                "Circular depends-on relationship between");
                                        }
                                        registerDependentBean(dep, beanName);
                                        try {
                                                getBean(dep);
                                        } catch (NoSuchBeanDefinitionException ex) {
                                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                                        }
                                }
                        }

                        if (mbd.isSingleton()) {
                                // getSingleton方法中会先从单例池查找Bean
                                // 如果没有则会调用lambda中的createBean(beanName, mbd, args)创建Bean并将其注册到单例池
                                // 所以此时放入单例池的是FactoryBean实例
                                sharedInstance = getSingleton(beanName, () -> {
                                        try {
                                                // 此处的beanName参数是不带&符的字符串
                                                return createBean(beanName, mbd, args);
                                        } catch (BeansException ex) {
                                                destroySingleton(beanName);
                                                throw ex;
                                        }
                                });
                                // beanName参数是不带&符的字符串
                                // name是原始的带&符的字符串
                                // 该方法里面会判断name是否有&符,如果有直接返回FactoryBean实例
                                // 如果没有&符会调用getObject()方法获取真正要暴露的Bean实例
                                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                        } else if (mbd.isPrototype()) {
                                Object prototypeInstance = null;
                                try {
                                        beforePrototypeCreation(beanName);
                                        prototypeInstance = createBean(beanName, mbd, args);
                                } finally {
                                        afterPrototypeCreation(beanName);
                                }
                                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                        } else {
                                String scopeName = mbd.getScope();
                                if (!StringUtils.hasLength(scopeName)) {
                                        throw new IllegalStateException("No scope name defined for bean");
                                }
                                Scope scope = this.scopes.get(scopeName);
                                if (scope == null) {
                                        throw new IllegalStateException("No Scope registered for scope name");
                                }
                                try {
                                        Object scopedInstance = scope.get(beanName, () -> {
                                                beforePrototypeCreation(beanName);
                                                try {
                                                        return createBean(beanName, mbd, args);
                                                } finally {
                                                        afterPrototypeCreation(beanName);
                                                }
                                        });
                                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                                } catch (IllegalStateException ex) {
                                        throw new BeanCreationException(beanName, "", ex);
                                }
                        }
                } catch (BeansException ex) {
                        cleanupAfterBeanCreationFailure(beanName);
                        throw ex;
                }
        }

        return (T) bean;
}

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

        // 判断name有&符,直接返回FactoryBean实例
        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;
                }
                return beanInstance;
        }

        if (!(beanInstance instanceof FactoryBean)) {
                return beanInstance;
        }

        Object object = null;
        if (mbd != null) {
                mbd.isFactoryBean = true;
        } else {
                // 从factoryBeanObjectCache池获取
                object = getCachedObjectForFactoryBean(beanName);
        }
        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());
                // 调用getObject()方法获取真正要暴露的Bean实例并将其放入factoryBeanObjectCache池
                object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: spring启动流程 (4) FactoryBean详解