whm9276 2017-09-14 02:42 采纳率: 0%
浏览 875

Spring factoryBean加载 框架内部嵌套加载问题

各位大神,最近在研究spring框架bean加载过程,遇到一个棘手问题,我相信研究spring原理的大神肯定对这个问题有兴趣

我的项目框架是spring+rpc,配置文件方式注入bean,非注解

一部分bean是普通的serivce bean配置,spring内部走正常bean的加载过程,没有问题;

还有一部分是自定义标签,通过一个工厂类生成service的代理对象bean,作为消费者/生产者,这个工厂类实现了FactoryBean接口,spring内部走FactoryBean的加载过程
public class RemoteServiceFactory implements FactoryBean, BeanFactoryAware, InitializingBean {
private static final Logger log = LoggerFactory.getLogger(RemoteServiceFactory.class);
 public RemoteServiceFactory(Object bean, String path, int port) {
  this.object = bean; // 自定义标签中配置的service bean的引用(ref属性,引用配置文件bean id)
  this.path = path; // 生产者服务路径(和此问题无关)
  this.port = port; // 生产者服务端口(和此问题无关)
 }
 
 public boolean isSingleton() {
  return true;
 }
 public void afterPropertiesSet() throws Exception {
   // 根据this.object创建相应的生产者/消费者代理对象,用于rpc
 }
}

问题分析,debug spring bean解析后的加载过程
1.spring对配置文件解析后,遍历所有的bean,进行一一实例化
  AbstractApplicationContext:finishBeanFactoryInitialization()
    内部调用beanFactory.preInstantiateSingletons();
      DefaultListableBeanFactory:preInstantiateSingletons()
        内部遍历beanNames,进行一一实例化

2.假如第一个bean是普通的service bean,在初始化时,会解析内部的依赖,然后遍历依赖参数,解析依赖
  DefaultListableBeanFactory:doResolveDependency()
    内部调用findAutowireCandidates() 
      内部调用BeanFactoryUtils.beanNamesForTypeIncludingAncestors()
        内部调用lbf.getBeanNamesForType()
          -> DefaultListableBeanFactory:doGetBeanNamesForType()
  关键就在这里,doGetBeanNamesForType方法内部会遍历所有bean,去判断是否匹配上面的依赖参数的类型,
  当遍历到实现FactoryBean的bean时,会实例化这个bean(因为FactoryBean只是代理,不是真正bean),然后又会解析factoryBean中真实bean中的依赖参数,
  然后就又会走到这里,导致一直嵌套下去的加载过程
  如果程序加载没有问题,则一切正常;一旦某个类加载失败(比如某个类注入的属性在properties中不存在),就会出现大量的异常信息抛出,
  原因就是上面的嵌套加载,某个类加载抛出异常会一直抛出到嵌套的最顶层,每一层的异常信息都会积攒下来,最后爆发似的抛出
  (每层的异常信息都是 当前这层bean的加载失败)

各位大神:
  我一直感觉spring这样嵌套加载在设计上是不应该的,不理解为什么会这样,单纯匹配类型的话,不能通过其他方式获取FactoryBean中真实bean的类型吗?
    为什么非要实例化它呢?有什么方法可以解决这个问题?

  • 写回答

1条回答 默认 最新

  • whm9276 2017-09-25 05:57
    关注

    顶起来,哪位大神帮看下

    评论

报告相同问题?

悬赏问题

  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 关于#python#的问题:自动化测试