0107Bean初始化-Bean生命周期详解-spring

文章目录

    • 1 前言
    • 2 Bean Aware接口回调
      • 2.1 Aware接口
      • 2.2 Aware接口回调逻辑
    • 3 Bean 初始化前阶段
      • 3.1 执行逻辑
      • 3.2 BeanPostProcessor两个重要实现类
        • 3.2.1 ApplicationContextAwareProcessor
        • 3.2.2 CommonAnnotationBeanPostProcessor
      • 3.3 小测试
    • 4 Bean 初始化操作
    • 5 Bean 初始化后操作
    • 6 所有单例bean初始化完成后阶段
    • 后记

1 前言

Bean初始化阶段又可细分为5个阶段:

  • Bean Aware接口回调
  • Bean 初始化前阶段
  • Bean 初始化操作
  • Bean 初始化后操作
  • Bean 初始化完成

2 Bean Aware接口回调

2.1 Aware接口

spring为我们提供了3个Aware接口,执行顺序如下:

  • BeanNameAware:beanName标记接口,setBeanName()方法获取创建bean的bean factory中beanName
  • BeanClassLoaderAware:bean 类加载器标记接口,setBeanClassLoader()获取加载该bean 类的类加载器
  • BeanFactoryAware:bean 创建工厂标记接口,setBeanFactory()方法获取创建该bean的bean factory。

示例代码:

package com.gaogzhen.myspring.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;

/**
 * Bean Aware 接口回调
 * @author: Administrator
 * @createTime: 2023/03/19 08:46
 */
public class AwareBean implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("这个Bean的类加载器是:" + classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("这个Bean的工厂对象是:" + beanFactory);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("这个Bean的名称是:" + name);
    }
}

// 测试方法
    @Test
    public void testBeanAware() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.registerBeanDefinition("awareBean", BeanDefinitionBuilder.genericBeanDefinition(AwareBean.class).getBeanDefinition());
        factory.getBean("awareBean");
    }

输出结果:

这个Bean的名称是:awareBean
这个Bean的类加载器是:jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
这个Bean的工厂对象是:org.springframework.beans.factory.support.DefaultListableBeanFactory@67304a40: defining beans [awareBean]; root of factory hierarchy

Aware为一个标记型接口,实现相应的子接口,可以获取spring相应的底层“组件”。

2.2 Aware接口回调逻辑

在上一篇属性赋值,即AbstractAutowireCapableBeanFactory的doCreate()中populateBean()方法。getBean()执行流程来到调用Aware接口部分代码:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
// 省略...
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
// 省略...
	}

继续执行initializeBean()初始化方法,代码如下:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		invokeAwareMethods(beanName, bean);
		// 省略...
	}

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

在invokeAwareMethods()方法中,顺序判断bean是否实现相应接口,如果实现相应接口,执行相应的方法。

3 Bean 初始化前阶段

3.1 执行逻辑

在initializeBean()方法中,执行完Aware回调之后,继续向下执行,来到Bean 初始化前阶段

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		// 省略...

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
	// 省略...
	}

@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

public interface BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
    // 省略...
}
  • applyBeanPostProcessorsAfterInitialization()方法遍历factory中注册的BeanPostProcessor,执行每个BeanPostProcessor的postProcessAfterInitialization方法(),返回最终的结果。
  • BeanPostProcessor:Bean后置处理器,postProcessBeforeInitialization()默认返回bean本身。

3.2 BeanPostProcessor两个重要实现类

3.2.1 ApplicationContextAwareProcessor

源代码如下:

class ApplicationContextAwareProcessor implements BeanPostProcessor {

   private final ConfigurableApplicationContext applicationContext;

   private final StringValueResolver embeddedValueResolver;


   /**
    * Create a new ApplicationContextAwareProcessor for the given context.
    */
   public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
      this.applicationContext = applicationContext;
      this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
   }


   @Override
   @Nullable
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
            bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
            bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
            bean instanceof ApplicationStartupAware)) {
         return bean;
      }

      invokeAwareInterfaces(bean);
      return bean;
   }

   private void invokeAwareInterfaces(Object bean) {
      if (bean instanceof Aware) {
         if (bean instanceof EnvironmentAware environmentAware) {
            environmentAware.setEnvironment(this.applicationContext.getEnvironment());
         }
         if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {
            embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);
         }
         if (bean instanceof ResourceLoaderAware resourceLoaderAware) {
            resourceLoaderAware.setResourceLoader(this.applicationContext);
         }
         if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {
            applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);
         }
         if (bean instanceof MessageSourceAware messageSourceAware) {
            messageSourceAware.setMessageSource(this.applicationContext);
         }
         if (bean instanceof ApplicationStartupAware applicationStartupAware) {
            applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());
         }
         if (bean instanceof ApplicationContextAware applicationContextAware) {
            applicationContextAware.setApplicationContext(this.applicationContext);
         }
      }
   }

}

ApplicationContextAwareProcessor的postProcessBeforeInitialization()方法会检测,如果bean实现了以下任一Aware接口,会执行相应Aware接口的方法:

  • EnvironmentAware:用于获取当前运行环境
  • EmbeddedValueResolverAware:获取StringValueResolver
  • ResourceLoaderAware:获取资源加载器
  • ApplicationEventPublisherAware:获取应用事件发布者
  • MessageSourceAware:获取消息源
  • ApplicationContextAware:获取应用上下文
  • ApplicationStartupAware:获取应用启动

ApplicationContext开头的,说明这个类只能在ApplicationContext环境中使用。

3.2.2 CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor调用@PostConstruct标注的方法

CommonAnnotationBeanPostProcessor调用postProcessBeforeInitialization()方法最终调用其父类InitDestroyAnnotationBeanPostProcessor中的方法,代码如下:

@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			metadata.invokeInitMethods(bean, beanName);
		}
		// 省略异常处理。。。
		return bean;
	}

3.3 小测试

定义一个类实现上述7个接口,一个方法加上@PostStruct注解,看下输出顺序和结果,测试类如下:

package com.gaogzhen.myspring.bean;

import jakarta.annotation.PostConstruct;
import org.springframework.beans.BeansException;
import org.springframework.context.*;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.util.StringValueResolver;

/**
 * 测试初始化前阶段
 * @author gaogzhen
 */
public class PostProcessBeforeInitializationBean implements EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationStartupAware ,ApplicationContextAware {

    @PostConstruct
    public void testPostProcessBeforeInitialization() {
        System.out.println("postConstruct");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext: " + applicationContext);
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("applicationEventPublisher: " + applicationEventPublisher);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("resolver: " + resolver);
    }

    @Override
    public void setEnvironment(Environment environment) {
        System.out.println("environment: " + environment);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("resourceLoader: " + resourceLoader);
    }

    @Override
    public void setApplicationStartup(ApplicationStartup applicationStartup) {
        System.out.println("applicationStartup: " + applicationStartup);
    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        System.out.println("messageSource: " + messageSource);
    }
}

// 测试代码
public void testPostProcessBeforeInitialization() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(PostProcessBeforeInitializationBean.class);
        context.refresh();
    }

测试结果:

environment: StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[PropertiesPropertySource@24039137 {name='systemProperties', properties={java.specification.version=17, sun.jnu.encoding=UTF-8, java.class.path=/Users/gaogzhen/.m2/repository/org/junit/platform/junit-platform-launcher/1.9.0/junit-platform-launcher-1.9.0.jar:// 省略。。。}]}
resolver: org.springframework.beans.factory.config.EmbeddedValueResolver@36546a22
resourceLoader: org.springframework.context.annotation.AnnotationConfigApplicationContext@5ba88be8, started on Tue Mar 21 11:44:23 CST 2023
applicationEventPublisher: org.springframework.context.annotation.AnnotationConfigApplicationContext@5ba88be8, started on Tue Mar 21 11:44:23 CST 2023
messageSource: org.springframework.context.annotation.AnnotationConfigApplicationContext@5ba88be8, started on Tue Mar 21 11:44:23 CST 2023
applicationStartup: org.springframework.core.metrics.DefaultApplicationStartup@60f7cc1d
applicationContext: org.springframework.context.annotation.AnnotationConfigApplicationContext@5ba88be8, started on Tue Mar 21 11:44:23 CST 2023
postConstruct

4 Bean 初始化操作

Bean初始化操作会执行2个步骤:

  • 执行InitializingBean接口的afterPropertiesSet()方法
  • 执行自定义的inti-method(初始化方法)

我们回到AbstractAutowireCapableBeanFactory的initializeBean()方法,继续跟踪

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	// 执行aware接口方法
   // 初始化前操作
   try {
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
// 省略。。。
   return wrappedBean;
}

继续执行invokeInitMethods()方法,代码如下:

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
      throws Throwable {

   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
      if (logger.isTraceEnabled()) {
         logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
      }
      ((InitializingBean) bean).afterPropertiesSet();
   }

   if (mbd != null && bean.getClass() != NullBean.class) {
      String[] initMethodNames = mbd.getInitMethodNames();
      if (initMethodNames != null) {
         for (String initMethodName : initMethodNames) {
            if (StringUtils.hasLength(initMethodName) &&
                  !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                  !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
               invokeCustomInitMethod(beanName, bean, mbd, initMethodName);
            }
         }
      }
   }
}

第一部分,InitializingBean接口相关

  • 判断是否实现InitializingBean接口,执行接口的afterPropertiesSet()方法
  • afterPropertiesSet方法由BeanFactory调用,在设置所有属性之后用于自定义的初始化或者校验。

第二部分,检查是否有自定义的初始化方法并执行自定义的初始化方法。

  • 自定义初始化方法,根据配置bean方法不同,设置方式不一样,这里以API的方式。
    • xml或者@Bean注解方式自己去测试

实例测试代码如下所示:

package com.gaogzhen.myspring.service;

import org.springframework.beans.factory.InitializingBean;

/**
 * @author gaogzhen
 */
public class InitializingService implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet");
    }

    public void initMethod() {
        System.out.println("自定义初始化方法");
    }
}

    @Test
    public void testInitializing() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(InitializingService.class)
                .setInitMethodName("initMethod")
                .getBeanDefinition();
        factory.registerBeanDefinition("initService", beanDefinition);
        System.out.println(factory.getBean("initService"));
    }

测试结果:

InitializingBean afterPropertiesSet
自定义初始化方法
com.gaogzhen.myspring.service.InitializingService@5674e1f2

5 Bean 初始化后操作

完成上面初始化操作后,我们在回到initializeBean()方法,看看接下来会执行什么?

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 省略。。。
// 初始化操作
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

进入applyBeanPostProcessorsAfterInitialization方法查看

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}
  • 调用BeanPostProcessor的postProcessAfterInitialization方法
  • postProcessAfterInitialization方法也称Bean初始化后置操作
  • 任意一个BeanPostProcessor的postProcessAfterInitialization返回null,该方法返回null
  • 全部执行完毕返回最后一个BeanPostProcessor的postProcessAfterInitialization方法的结果

测试示例代码如下:

@Test
public void testAfterInitializaiton() {
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    factory.addBeanPostProcessor(new BeanPostProcessor() {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println(beanName + "==postProcessAfterInitialization==" + bean);
            return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
        }
    });
    BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(String.class)
            .addConstructorArgValue("公众号【我眼中的互联网世界】")
            .getBeanDefinition();
    factory.registerBeanDefinition("afterInit", beanDefinition);
    System.out.println(factory.getBean("afterInit"));
}

测试结果:

afterInit==postProcessAfterInitialization==公众号【我眼中的互联网世界】
公众号【我眼中的互联网世界】

6 所有单例bean初始化完成后阶段

所有单例bean实例化完成之后,spring会回调下面这个接口:

public interface SmartInitializingSingleton {
    void afterSingletonsInstantiated();
}

调用逻辑在下面这个方法中

/* 确保所有非lazy的单例都被实例化,同时考虑到FactoryBeans。如果需要,通常在工厂设置结束时调用。
*/
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
这个方法内部会先触发所有非延迟加载的单例bean初始化,然后从容器中找到类型是SmartInitializingSingleton的bean,调用他们的afterSingletonsInstantiated方法。

我们通过ApplicaitonContext常用的refresh方法来追踪下,首先来到AbstractApplication中的fresh方法

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
    // 省略。。。

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

  //省略。。。
}

finishBeanFactoryInitialization初始化所有剩余的非懒惰初始化的beans,代码如下

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // 省略。。。

   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();
}

执行BeanFactory的preInstantiateSingletons方法,实际调用DefaultListableBeanFactory的preInstantiateSingletons方法,代码如下:

@Override
public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
               getBean(beanName);
            }
         }
         else {
            getBean(beanName);
         }
      }
   }

   // Trigger post-initialization callback for all applicable beans...
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
         StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
               .tag("beanName", beanName);
         smartSingleton.afterSingletonsInstantiated();
         smartInitialize.end();
      }
   }
}

示例测试,通过ApplicationContext自动回调SmartInitializingSingleton:

package com.gaogzhen.myspring.service;

import org.springframework.stereotype.Service;

/**
 * 测试SmartInitializingSingleton
 * @author gaogzhen
 */
@Service
public class Service1 {
    public Service1() {
        System.out.println("service1 初始化完成");
    }
}
package com.gaogzhen.myspring.service;

import org.springframework.stereotype.Service;

/**
 * 测试SmartInitializingSingleton
 * @author gaogzhen
 */
@Service
public class Service2 {
    public Service2() {
        System.out.println("service2 初始化完成");
    }
}
package com.gaogzhen.myspring.processors;

import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;

/**
 * @author gaogzhen
 */
@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("所有bean初始化完毕");
    }
}
package com.gaogzhen.myspring.test;

import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = {"com.gaogzhen.myspring"})
public class TestSmartInitializingSingleton {

    @Test
    public void testAfterSingletonsInstantiated() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(TestSmartInitializingSingleton.class);
        System.out.println("开始启动容器");
        context.refresh();
        System.out.println("容器启动完毕");
    }
}

测试结果:

开始启动容器
// 省略日志信息。。。
2023-03-22 10:19:02 407 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'service1'
service1 初始化完成
2023-03-22 10:19:02 407 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'service2'
service2 初始化完成
所有bean初始化完毕
容器启动完毕

后记

如果小伙伴什么问题或者指教,欢迎交流。

❓QQ:806797785

⭐️源代码仓库地址:https://gitee.com/gaogzhen/spring6-study

参考:

[1]Spring系列之Bean生命周期详解[CP/OL]

你可能感兴趣的:(spring,Bean生命周期,Bean初始化,Java)