Bean的生命周期(二)

简介: Bean的生命周期

属性填充

功能:对bean中需要自动装配的属性进行填充

角色:

1、AutowiredAnnotationBeanPostProcessor

2、CommonAnnotationBeanPostProcessor

在上一个流程中,我们已经找到了所有需要自动装配的Member,所以这一部流程就显得非常简单了

我们同样以AutowiredAnnotationBeanPostProcessor为例

1、使用beanName为key,从缓存中取出InjectionMetadata

2、遍历InjectionMetadata中的checkedElements集合

3、取出Element中的Member,根据Member的类型在Spring中获取Bean

4、使用反射将获取到的Bean设值到属性中

推导过程

在Spring中,Bean填充属性之后还可以做一些初始化的逻辑,比如Spring的线程池ThreadPoolTaskExecutor在填充属性之后的创建线程池逻辑,RedisTemplate的设置默认值。

Spring的初始化逻辑共分为4个部分:

1、invokeAwareMethods:调用实现特定Aware接口的方法

2、applyBeanPostProcessorsBeforeInitialization:初始化前的处理

3、invokeInitMethods:调用初始化方法

4、applyBeanPostProcessorsAfterInitialization:初始化后的处理

invokeAwareMethods

这块逻辑非常简单,我直接把源码粘出来给大家看看就明白了

private void invokeAwareMethods(String beanName, 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);
      }
    }
  }

初始化前的处理

功能:调用初始化方法前的一些操作

角色:

1、InitDestroyAnnotationBeanPostProcessor:处理@PostContrust注解

2、ApplicationContextAwareProcessor:处理一系列Aware接口的回调方法

这一步骤的功能没有太大的关联性,完全按照使用者自己的意愿决定想在初始化方法前做些什么,我们一个一个来过

1.InitDestroyAnnotationBeanPostProcessor

这里的逻辑与属性填充过程非常相似,属性填充过程是取出自动装配相关的InjectionMetadata进行处理,而这一步则是取@PostContrust相关的Metadata进行处理,这个Metadata同样也是在处理BeanDefinition过程解析缓存的

1、取出处理BeanDefinition过程解析的LifecycleMetadata

2、遍历LifecycleMetadata中的checkedInitMethods集合

3、使用反射进行调用

2.ApplicationContextAwareProcessor

这一步与invokeAwareMethods大同小异,只不过是其他的一些Aware接口,同样直接粘上代码

  private void invokeAwareInterfaces(Object bean) {
    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);
    }
  }

初始化方法

在Spring中的初始化方法有两种

1、实现InitializingBean接口的afterPropertiesSet方法

2、@Bean注解中的initMethod属性

调用顺序是先调用afterPropertiesSetinitMethod

1、判断Bean是否实现InitializingBean接口

2、是则将Bean强转成InitializingBean,调用afterPropertiesSet方法

3、判断BeanDefinition中是否有initMethod

4、是则找到对应的initMethod,通过反射进行调用

初始化后的处理

在Spring的内置的后置处理器中,该步骤只有ApplicationListenerDetector有相应处理逻辑:将实现了ApplicationListener接口的bean添加到事件监听器列表中

如果使用了Aop相关功能,则会使用到AbstractAutoProxyCreator,进行创建代理对象。

ApplicationListenerDetector的流程如下

1、判断Bean是否是个ApplicationListener

2、是则将bean存放到applicationContext的监听器列表中

补充流程图

到这里,Bean的生命周期主要部分已经介绍完了,我们将流程图补充一下

同样还有其他的一些逻辑

1、中止创建Bean的过程

该过程处于Bean生命周期的最开始部分。

功能:由后置处理器返回Bean,达到中止创建Bean的效果

角色:无,Spring的内置后置处理器中,无实现。

Bean的生命周期十分复杂,Spring允许你直接拦截,即在创建Bean之前由自定义的后置处理器直接返回一个Bean给Spring,那么Spring就会使用你给的Bean,不会再走Bean生命周期流程。

案例演示:

@Component
public class Car {
  @Autowired
  private Person person;
  public void checkPerson(){
    if(person == null){
      System.out.println("person is null");
    }
  }
}

由于在Person属性上加了@Autowired,所以正常来说person必然不能为空,因为这是必须要注入的。

现在我们自定义一个BeanPostProcessor进行拦截

@Component
public class InterruptBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
  @Override
  public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    if("car".equals(beanName)){
      try {
        return beanClass.newInstance();
      } catch (InstantiationException | IllegalAccessException e) {
        e.printStackTrace();
      }
    }
    return null;
  }
}

测试结果如下

2、提前缓存刚实例化的对象

该步骤跟随在Spring实例化bean之后,将bean进行缓存,其目的是为了解决循环依赖问题。

该过程暂时按下不表,单独提出放于循环依赖章节。

3、中止填充属性操作

与中止创建Bean逻辑相同,Spring同样也允许你在属性填充前进行拦截。在Spring的内置处理器中同样无该实现。

实现手段为实现InstantiationAwareBeanPostProcessor接口,在postProcessAfterInstantiation方法中返回false

@Component
public class InterruptBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
  @Override
  public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    if(beanName.equals("car")){
      return false;
    }
    return true;
  }
}

4、注册Bean的销毁方法

Spring中不仅有@PostContrustafterPropertiesinitMethod这些bean创建时的初始化方法,同样也有bean销毁时的@PreDestorydestroy,destroyMethod

所以在Bean的生命周期最后一步,Spring会将具备这些销毁方法的Bean注册到销毁集合中,用于系统关闭时进行回调。

比如线程池的关闭,连接池的关闭,注册中心的取消注册,都是通过它来实现的。

完整流程图

最后,附上一张Bean生命周期的完整流程图

目录
相关文章
|
7月前
|
前端开发 Java 开发者
Bean的生命周期和作用域
Bean的生命周期和作用域
|
3月前
|
Java 开发者 Spring
Bean生命周期介绍
Spring Boot 的 Bean 生命周期管理是其核心功能之一,负责应用程序中 Java 对象(称为 Beans)的创建、配置、初始化和销毁。此功能提供了灵活的依赖注入方式,便于组件化开发。Bean 生命周期包括实例化、属性注入、初始化方法调用、使用及销毁方法调用等阶段。应用场景涵盖依赖注入、配置管理、组件扩展及切面编程。通过实现特定接口或注解,开发者可轻松管理对象生命周期,优化应用性能。示例代码展示了如何通过日志观察 Bean 生命周期的不同阶段。
120 3
|
7月前
|
XML Java 数据格式
Spring框架学习 -- Bean的生命周期和作用域
Spring框架学习 -- Bean的生命周期和作用域
58 2
|
XML Java 数据格式
spring之bean的生命周期以及单例多例的区别
spring之bean的生命周期以及单例多例的区别
147 0
|
7月前
|
存储 设计模式 Java
Bean 作用域和生命周期
Bean 作用域和生命周期
|
Java 容器 Spring
Bean生命周期
Bean生命周期
|
7月前
|
Java 开发者 Spring
Bean 的生命周期了解么
Bean 的生命周期了解么
|
Java Spring 容器
bean的生命周期
bean的生命周期
57 0
|
存储 安全 Java
Bean 的作用域和生命周期
Bean 的作用域和生命周期
79 1
|
XML Java 数据格式
Bean 的生命周期
Bean 的生命周期介绍