spring启动流程 (4) FactoryBean详解

海哥  金牌会员 | 2023-7-11 09:17:51 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 534|帖子 534|积分 1602

FactoryBean接口

实现类对象将被用作创建Bean实例的工厂,即调用getObject()方法返回的对象才是真正要使用的Bean实例,而不是直接将FactoryBean对象作为暴露的Bean实例。
FactoryBeans可以支持singleton和prototype,并且可以根据需要懒加载或在启动时立即创建对象。
这个接口在编写扫描接口生成代理对象的场景下经常使用,比如Mybatis Mapper接口扫描、Dubbo接口扫描、Feign接口扫描等。
Spring容器只负责管理FactoryBean实例的生命周期,而不是FactoryBean创建的对象的生命周期。因此不会自动调用暴露的Bean对象的destroy方法。FactoryBean应该实现DisposableBean,并将关闭调用委托给底层对象。
  1. public interface FactoryBean<T> {
  2.         /**
  3.          * Return an instance (possibly shared or independent) of the object
  4.          * managed by this factory.
  5.          */
  6.         T getObject() throws Exception;
  7.         /**
  8.          * Return the type of object that this FactoryBean creates,
  9.          * or null if not known in advance.
  10.          */
  11.         Class<?> getObjectType();
  12.         /**
  13.          * Is the object managed by this factory a singleton?
  14.          */
  15.         default boolean isSingleton() {
  16.                 return true;
  17.         }
  18. }
复制代码
我们可以使用正常的getBean(beanName)方式获取通过getObject()方法暴露的Bean实例,也可以使用getBean("&" + beanName)方式获取FactoryBean的实例。
下文将介绍其实现方式。
FactoryBean的实现方式

Spring创建单例Bean的逻辑在DefaultListableBeanFactory的preInstantiateSingletons()方法中:
  1. public void preInstantiateSingletons() throws BeansException {
  2.         List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  3.         // Trigger initialization of all non-lazy singleton beans...
  4.         for (String beanName : beanNames) {
  5.                 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  6.                 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
  7.                         if (isFactoryBean(beanName)) {
  8.                                 // 此处使用"& + beanName"作为beanName创建FactoryBean实例
  9.                                 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
  10.                                 if (bean instanceof FactoryBean) {
  11.                                         FactoryBean<?> factory = (FactoryBean<?>) bean;
  12.                                         boolean isEagerInit;
  13.                                         if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
  14.                                                 isEagerInit = AccessController.doPrivileged(
  15.                                                                 (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
  16.                                                                 getAccessControlContext());
  17.                                         } else {
  18.                                                 isEagerInit = (factory instanceof SmartFactoryBean &&
  19.                                                                 ((SmartFactoryBean<?>) factory).isEagerInit());
  20.                                         }
  21.                                         if (isEagerInit) {
  22.                                                 getBean(beanName);
  23.                                         }
  24.                                 }
  25.                         } else {
  26.                                 getBean(beanName);
  27.                         }
  28.                 }
  29.         }
  30.         // Trigger post-initialization callback for all applicable beans...
  31.         // ...
  32. }
  33. public Object getBean(String name) throws BeansException {
  34.         return doGetBean(name, null, null, false);
  35. }
  36. protected <T> T doGetBean(
  37.                 String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly)
  38.                 throws BeansException {
  39.         // 此步骤将&符移除
  40.         String beanName = transformedBeanName(name);
  41.         Object bean;
  42.         Object sharedInstance = getSingleton(beanName);
  43.         if (sharedInstance != null && args == null) {
  44.                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  45.         } else {
  46.                 if (isPrototypeCurrentlyInCreation(beanName)) {
  47.                         throw new BeanCurrentlyInCreationException(beanName);
  48.                 }
  49.                 BeanFactory parentBeanFactory = getParentBeanFactory();
  50.                 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  51.                         String nameToLookup = originalBeanName(name);
  52.                         if (parentBeanFactory instanceof AbstractBeanFactory) {
  53.                                 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
  54.                                                 nameToLookup, requiredType, args, typeCheckOnly);
  55.                         } else if (args != null) {
  56.                                 return (T) parentBeanFactory.getBean(nameToLookup, args);
  57.                         } else if (requiredType != null) {
  58.                                 return parentBeanFactory.getBean(nameToLookup, requiredType);
  59.                         } else {
  60.                                 return (T) parentBeanFactory.getBean(nameToLookup);
  61.                         }
  62.                 }
  63.                 if (!typeCheckOnly) {
  64.                         markBeanAsCreated(beanName);
  65.                 }
  66.                 try {
  67.                         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  68.                         checkMergedBeanDefinition(mbd, beanName, args);
  69.                         String[] dependsOn = mbd.getDependsOn();
  70.                         if (dependsOn != null) {
  71.                                 for (String dep : dependsOn) {
  72.                                         if (isDependent(beanName, dep)) {
  73.                                                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  74.                                                                 "Circular depends-on relationship between");
  75.                                         }
  76.                                         registerDependentBean(dep, beanName);
  77.                                         try {
  78.                                                 getBean(dep);
  79.                                         } catch (NoSuchBeanDefinitionException ex) {
  80.                                                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  81.                                                                 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
  82.                                         }
  83.                                 }
  84.                         }
  85.                         if (mbd.isSingleton()) {
  86.                                 // getSingleton方法中会先从单例池查找Bean
  87.                                 // 如果没有则会调用lambda中的createBean(beanName, mbd, args)创建Bean并将其注册到单例池
  88.                                 // 所以此时放入单例池的是FactoryBean实例
  89.                                 sharedInstance = getSingleton(beanName, () -> {
  90.                                         try {
  91.                                                 // 此处的beanName参数是不带&符的字符串
  92.                                                 return createBean(beanName, mbd, args);
  93.                                         } catch (BeansException ex) {
  94.                                                 destroySingleton(beanName);
  95.                                                 throw ex;
  96.                                         }
  97.                                 });
  98.                                 // beanName参数是不带&符的字符串
  99.                                 // name是原始的带&符的字符串
  100.                                 // 该方法里面会判断name是否有&符,如果有直接返回FactoryBean实例
  101.                                 // 如果没有&符会调用getObject()方法获取真正要暴露的Bean实例
  102.                                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  103.                         } else if (mbd.isPrototype()) {
  104.                                 Object prototypeInstance = null;
  105.                                 try {
  106.                                         beforePrototypeCreation(beanName);
  107.                                         prototypeInstance = createBean(beanName, mbd, args);
  108.                                 } finally {
  109.                                         afterPrototypeCreation(beanName);
  110.                                 }
  111.                                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  112.                         } else {
  113.                                 String scopeName = mbd.getScope();
  114.                                 if (!StringUtils.hasLength(scopeName)) {
  115.                                         throw new IllegalStateException("No scope name defined for bean");
  116.                                 }
  117.                                 Scope scope = this.scopes.get(scopeName);
  118.                                 if (scope == null) {
  119.                                         throw new IllegalStateException("No Scope registered for scope name");
  120.                                 }
  121.                                 try {
  122.                                         Object scopedInstance = scope.get(beanName, () -> {
  123.                                                 beforePrototypeCreation(beanName);
  124.                                                 try {
  125.                                                         return createBean(beanName, mbd, args);
  126.                                                 } finally {
  127.                                                         afterPrototypeCreation(beanName);
  128.                                                 }
  129.                                         });
  130.                                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  131.                                 } catch (IllegalStateException ex) {
  132.                                         throw new BeanCreationException(beanName, "", ex);
  133.                                 }
  134.                         }
  135.                 } catch (BeansException ex) {
  136.                         cleanupAfterBeanCreationFailure(beanName);
  137.                         throw ex;
  138.                 }
  139.         }
  140.         return (T) bean;
  141. }
  142. protected Object getObjectForBeanInstance(
  143.                 Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
  144.         // 判断name有&符,直接返回FactoryBean实例
  145.         if (BeanFactoryUtils.isFactoryDereference(name)) {
  146.                 if (beanInstance instanceof NullBean) {
  147.                         return beanInstance;
  148.                 }
  149.                 if (!(beanInstance instanceof FactoryBean)) {
  150.                         throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
  151.                 }
  152.                 if (mbd != null) {
  153.                         mbd.isFactoryBean = true;
  154.                 }
  155.                 return beanInstance;
  156.         }
  157.         if (!(beanInstance instanceof FactoryBean)) {
  158.                 return beanInstance;
  159.         }
  160.         Object object = null;
  161.         if (mbd != null) {
  162.                 mbd.isFactoryBean = true;
  163.         } else {
  164.                 // 从factoryBeanObjectCache池获取
  165.                 object = getCachedObjectForFactoryBean(beanName);
  166.         }
  167.         if (object == null) {
  168.                 // Return bean instance from factory.
  169.                 FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
  170.                 // Caches object obtained from FactoryBean if it is a singleton.
  171.                 if (mbd == null && containsBeanDefinition(beanName)) {
  172.                         mbd = getMergedLocalBeanDefinition(beanName);
  173.                 }
  174.                 boolean synthetic = (mbd != null && mbd.isSynthetic());
  175.                 // 调用getObject()方法获取真正要暴露的Bean实例并将其放入factoryBeanObjectCache池
  176.                 object = getObjectFromFactoryBean(factory, beanName, !synthetic);
  177.         }
  178.         return object;
  179. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

海哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表