美文网首页
Spring-01-bean生命周期详解(源码版)

Spring-01-bean生命周期详解(源码版)

作者: 誓俭草 | 来源:发表于2019-11-02 21:15 被阅读0次

    spring -bean生命周期

    1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化

    2. Bean实例化后对将Bean的引入和值注入到Bean的属性中

      1. 通过打断点可看到spring默认会通过DefaultListableBeanFactory类为我们创建实例对象
      DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 576  
      

      打开对应的方法如下:

      protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
               throws BeanCreationException {
      
           // Instantiate the bean.
           BeanWrapper instanceWrapper = null;
           if (mbd.isSingleton()) {
               instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
           }
           //看以看到此处为创建实例化对象代码
           if (instanceWrapper == null) {
               instanceWrapper = createBeanInstance(beanName, mbd, args);
           }
           
           Object exposedObject = bean;
           try {
                  //通过读源码注解可知道populateBean方法时用来给实例化bean赋值
               populateBean(beanName, mbd, instanceWrapper);
                  //initializeBean此方法则是用来初始化的方法
               exposedObject = initializeBean(beanName, exposedObject, mbd);
           }
           catch (Throwable ex) {
               if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                   throw (BeanCreationException) ex;
               }
               else {
                   throw new BeanCreationException(
                           mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
               }
           }
           // Register bean as disposable.
           try {
               registerDisposableBeanIfNecessary(beanName, bean, mbd);
           }
           catch (BeanDefinitionValidationException ex) {
               throw new BeanCreationException(
                       mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
           }
      
           return exposedObject;
       }
      
    1. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法

    2. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入

      1)我们可以在Bean实现的setBeanName方法中打断点看下实现方式

      找到源码如下:在Bean执行初始化initializeBean方法的时候

      DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).initializeBean(String, Object, RootBeanDefinition) line: 1731 
      

      执行了invokeAwareMethods此方法:

      protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
           if (System.getSecurityManager() != null) {
               AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                   invokeAwareMethods(beanName, bean);
                   return null;
               }, getAccessControlContext());
           }
           else {
                  //执行了此方法
               invokeAwareMethods(beanName, bean);
           }
      
           Object wrappedBean = bean;
           if (mbd == null || !mbd.isSynthetic()) {
               wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
           }
               invokeInitMethods(beanName, wrappedBean, mbd);
      }
      
      //此方法则会根据bean的实现类去调用他的实现方法   
      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);
               }
           }
       }
      
    3. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。

      1)此处调用的则是initializeBean方法中的一下代码

      DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyBeanPostProcessorsBeforeInitialization(Object, String) line: 419 
      

      同时可以知道调用了此类ApplicationContextAwareProcessor的postProcessBeforeInitialization方法

      ApplicationContextAwareProcessor.postProcessBeforeInitialization(Object, String) line: 96
      

      源码如下:

      public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
           AccessControlContext acc = null;
      
           if (System.getSecurityManager() != null &&
                   (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                           bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                           bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
               acc = this.applicationContext.getBeanFactory().getAccessControlContext();
           }
      
           if (acc != null) {
               AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                   //此方法就是调用对应的实现方法
                      invokeAwareInterfaces(bean);
                   return null;
               }, acc);
           }
           else {
               invokeAwareInterfaces(bean);
           }
      
           return bean;
       }
      
    1. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。

      通过以上方法可以知道spring底层也时使用了此接口,例如上面所说的ApplicationContextAwareProcessor
      
    2. 可以在bean对应方法上添加@PostConstruct注解,也可以在Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用

    3. 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。

    4. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。

    5. 可以在bean对应方法上添加@PreDestroy注解,也可以在bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

    相关文章

      网友评论

          本文标题:Spring-01-bean生命周期详解(源码版)

          本文链接:https://www.haomeiwen.com/subject/jvvhbctx.html