【小家Spring】AbstractAutowireCapableBeanFactory#populateBean实现Bean的属性赋值和initializeBean对Bean的初始化(下)

简介: 【小家Spring】AbstractAutowireCapableBeanFactory#populateBean实现Bean的属性赋值和initializeBean对Bean的初始化(下)

invokeAwareMethods:相关Aware接口为:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware

这些都是spring将数据暴露出去的一种方式,我们直接实现这个接口就能拿到了~


  private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
        ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
        ClassLoader bcl = getBeanClassLoader();
        if (bcl != null) {
          ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
        }
      }
      if (bean instanceof BeanFactoryAware) {
        ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
    }
  }


applyBeanPostProcessorsBeforeInitialization的重要实现解释如下:


//ApplicationContextAwareProcessor:核心处理为
  private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof Aware) {
      if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
      }
      if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
    }
  }
//BeanValidationPostProcessor:对bean进行数据校验
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (!this.afterInitialization) {
      doValidate(bean);
    }
    return bean;
  }
//BootstrapContextAwareProcessor
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (this.bootstrapContext != null && bean instanceof BootstrapContextAware) {
      ((BootstrapContextAware) bean).setBootstrapContext(this.bootstrapContext);
    }
    return bean;
  }
//ServletContextAwareProcessor:
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (getServletContext() != null && bean instanceof ServletContextAware) {
      ((ServletContextAware) bean).setServletContext(getServletContext());
    }
    if (getServletConfig() != null && bean instanceof ServletConfigAware) {
      ((ServletConfigAware) bean).setServletConfig(getServletConfig());
    }
    return bean;
  }
//LoadTimeWeaverAwareProcessor
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof LoadTimeWeaverAware) {
      LoadTimeWeaver ltw = this.loadTimeWeaver;
      if (ltw == null) {
        Assert.state(this.beanFactory != null,
            "BeanFactory required if no LoadTimeWeaver explicitly specified");
        ltw = this.beanFactory.getBean(
            ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME, LoadTimeWeaver.class);
      }
      ((LoadTimeWeaverAware) bean).setLoadTimeWeaver(ltw);
    }
    return bean;
  }
//InitDestroyAnnotationBeanPostProcessor:处理声明周期注解方法的处理器。有了它,就允许用注解代替去实现Spring的接口InitializingBean和DisposableBean了。
//比如@PostConstruct和@PreDestroy等
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
      metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
      throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
  }


applyBeanPostProcessorsAfterInitialization的重要实现解释如下:


image.png


Aop相关的几个实现,这里先不做解释,等到后面AOP文章会专门解析~~~~~~


//ApplicationListenerDetector:把所有的ApplicationListener的Bean,都加入到addApplicationListener里面,放到广播器里面
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean instanceof ApplicationListener) {
      // potentially not detected as a listener by getBeanNamesForType retrieval
      Boolean flag = this.singletonNames.get(beanName);
      if (Boolean.TRUE.equals(flag)) {
        // singleton bean (top-level or inner): register on the fly
        this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
      }
      else if (Boolean.FALSE.equals(flag)) {
        if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
          // inner bean with other scope - can't reliably process events
          logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
              "but is not reachable for event multicasting by its containing ApplicationContext " +
              "because it does not have singleton scope. Only top-level listener beans are allowed " +
              "to be of non-singleton scope.");
        }
        this.singletonNames.remove(beanName);
      }
    }
    return bean;
  }
//BeanValidationPostProcessor:校验
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (this.afterInitialization) {
      doValidate(bean);
    }
    return bean;
  }
//ScheduledAnnotationBeanPostProcessor:解析方法中标注有@Scheduled注解的 然后加入当作一个任务进行执行
  @Override
  public Object postProcessAfterInitialization(final Object bean, String beanName) {
    Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
    if (!this.nonAnnotatedClasses.contains(targetClass)) {
      Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,
          (MethodIntrospector.MetadataLookup<Set<Scheduled>>) method -> {
            Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(
                method, Scheduled.class, Schedules.class);
            return (!scheduledMethods.isEmpty() ? scheduledMethods : null);
          });
      if (annotatedMethods.isEmpty()) {
        this.nonAnnotatedClasses.add(targetClass);
        if (logger.isTraceEnabled()) {
          logger.trace("No @Scheduled annotations found on bean class: " + bean.getClass());
        }
      }
      else {
        // Non-empty set of methods
        annotatedMethods.forEach((method, scheduledMethods) ->
            scheduledMethods.forEach(scheduled -> processScheduled(scheduled, method, bean)));
        if (logger.isDebugEnabled()) {
          logger.debug(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName +
              "': " + annotatedMethods);
        }
      }
    }
    return bean;
  }
//SimpleServletPostProcessor:这个很有意思。 相当于当Servlet是以Bean的形式注入容器的时候,Bean初始化完成后,会自动调用它的init方法~~~~~~~~
//如果config为null,那么它传入可能为代理的DelegatingServletConfig
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof Servlet) {
      ServletConfig config = this.servletConfig;
      if (config == null || !this.useSharedServletConfig) {
        config = new DelegatingServletConfig(beanName, this.servletContext);
      }
      try {
        ((Servlet) bean).init(config);
      }
      catch (ServletException ex) {
        throw new BeanInitializationException("Servlet.init threw exception", ex);
      }
    }
    return bean;
  }



整个初始化流程如下

1.调用各类感知Aware接口


2.执行applyBeanPostProcessorsBeforeInitialization初始化前的 处置操作


3.调用InitializingBean接口初始化 (如果配置了method-init,则调用其方法初始化 )


4.调用applyBeanPostProcessorsAfterInitialization 初始化之后的处置操作


总结


populateBean和initializeBean完成了我们Spring IOC容器的核心内容:依赖注入。前面做的都是非常非常多的准备工作,同时这里也调用了可以参与Bean生命周期的各种钩子方法。

Spring非常非常优秀的一个设计:是我前面强调过多次的职责单一原则,每一个功能,甚至每一个步骤都由特殊的处理器(或者工具类)来完成。优秀的设计,成就了Spring它的扩展能力极强,我们甚至可以在不知道Spring原理的情况下,流畅的使用它的各项功能。(比如Spring AOP、声明式事务、Schedule等等)

相关文章
|
1月前
|
XML 安全 Java
|
12天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
12天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
18天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
54 6
|
20天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
84 3
|
2月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
1月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
35 1
|
3月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
261 2
|
13天前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
20天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
75 14

热门文章

最新文章