设为首页 加入收藏

TOP

Spring源码:Bean的生命周期(二)(二)
2023-07-25 21:28:40 】 浏览:59
Tags:Spring 源码 Bean 周期
,否则会走单例 Bean 的创建逻辑。
  • 当所有单例非懒加载的 Bean 创建完成后,Spring会遍历所有单例 Bean,判断其是否为 SmartInitializingSingleton 类型。如果是,则会自动调用 afterSingletonsInstantiated 方法。
  • isFactoryBean

    由于创建 Bean 的逻辑比较复杂,其中包含了许多细节,因此,在这里我们特别提到了一个方法 isFactoryBean()。之所以要提到这个方法,是因为Spring支持使用 FactoryBean 来创建复杂对象。下面是该方法的主要源码:

    public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {  
       String beanName = transformedBeanName(name);  
       Object beanInstance = getSingleton(beanName, false);  
       if (beanInstance != null) {  
          return (beanInstance instanceof FactoryBean);  
       }  
       // No singleton instance found -> check bean definition.  
      if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {  
          // No bean definition found in this factory -> delegate to parent.  
      return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);  
       }  
       return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));  
    }
    

    大致逻辑如下:

    1. transformedBeanName 的作用是不管传入的参数是 &××× 还是 ×××,都返回 ×××。这是因为Spring标记 FactoryBean 时使用 &××× 作为 FactoryBeanbeanName
    2. getSingleton 方法从单例池中获取 Bean 实例,如果该实例是 FactoryBean,则直接返回该实例。
    3. 如果 BeanFactory 中的 Bean 定义 Map 中不包含该 beanNameBean 定义,并且当前 BeanFactory 的父 BeanFactory 实现了 ConfigurableBeanFactory 接口,那么就需要查看当前父 BeanFactory 中是否有该实例,并且判断该实例是否为 FactoryBean。举个例子来说:
    // 创建一个父Spring容器  
    AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();  
    parent.register(AppConfig.class);  
    parent.refresh();  
    // 创建一个Spring容器  
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();  
    applicationContext.setParent(parent);  
    applicationContext.register(AppConfig1.class);  
    applicationContext.refresh();  
    UserService bean = applicationContext.getBean(UserService.class);  
    bean.test();
    
    1. 如果并没有实例化出来的bean,那么对bean定义进行判断。
    protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {  
       Boolean result = mbd.isFactoryBean;  
       if (result == null) {  
          // 根据BeanDefinition推测Bean类型(获取BeanDefinition的beanClass属性)  
      Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);  
          // 判断是不是实现了FactoryBean接口  
      result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));  
          mbd.isFactoryBean = result;  
       }  
       return result;  
    }
    

    注释也基本写好了,基本上就是根据BeanDefinition推测Bean类型(获取BeanDefinition的beanClass属性),再根据bean类型判断是不是实现了FactoryBean接口,然后返回判断结果。

    SmartFactoryBean

    getBean 方法中,我们可以获取 FactoryBean 的实例并返回。接下来的步骤是判断当前的 FactoryBean 是否实现了 SmartFactoryBean 接口。需要注意的是,SmartFactoryBeanFactoryBean 接口的一个子接口。虽然我们在实现 FactoryBean 接口时不必实现 SmartFactoryBean 接口,但是如果实现了 SmartFactoryBean 接口,那么在创建 FactoryBean 时就会调用 getObject 方法返回实例。正常情况下,只有当容器启动完成后才会调用 getObject 方法。如果我们想在初始化时就调用,可以这样实现:

    @Component  
    public class UserFactory implements SmartFactoryBean {  
     
       @Override  
      public Object getObject() throws Exception {  
          return new User();  
       }  
      
       @Override  
      public Class<?> getObjectType() {  
          return User.class;  
       }  
      
       @Override  
      public boolean isEagerInit() {  
          return true;  
       }  
    }
    

    结语

    FactoryBean 和 BeanFactory 是两个不同的概念。前者是一个接口,我们可以在实现该接口时通过调用 getObject 方法来返回实例,同时 FactoryBean 本身也是一个实例。后者是 Spring 容器的工厂,通过其中的 bean 定义 Map 一个一个地实例化我们通过注解等方式注入进去的 bean 工厂。在判断 FactoryBean 时,如果当前 B

    首页 上一页 1 2 3 下一页 尾页 2/3/3
    】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
    上一篇用Aspose-Java免费实现 PDF、Word.. 下一篇Java-方法重载

    最新文章

    热门文章

    Hot 文章

    Python

    C 语言

    C++基础

    大数据基础

    linux编程基础

    C/C++面试题目