您的位置:首页 > 游戏 > 游戏 > Spring扩展点系列-@PostConstruct

Spring扩展点系列-@PostConstruct

2025/2/13 6:07:05 来源:https://blog.csdn.net/qq_32590535/article/details/141683719  浏览:    关键词:Spring扩展点系列-@PostConstruct

简介

spring的Bean在创建的时候会进行初始化,而初始化过程会解析出@PostConstruct注解的方法,并反射调用该方法。
@PostConstruct 的使用和特点

  • 只有一个非静态方法能使用此注解;
  • 被注解的方法不得有任何参数;
  • 被注解的方法返回值必须为void;
  • 被注解的方法不得抛出已检查异常;
  • 被注解的方法只会被执行一次;
spring容器中Bean的生命周期内所有可扩展的点的调用顺序
扩展接口 实现接口
ApplicationContextlnitializer initialize
AbstractApplicationContext refreshe
BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry
BeanDefinitionRegistryPostProcessor postProcessBeanFactory
BeanFactoryPostProcessor postProcessBeanFactory
instantiationAwareBeanPostProcessor postProcessBeforelnstantiation
SmartlnstantiationAwareBeanPostProcessor determineCandidateConstructors
MergedBeanDefinitionPostProcessor postProcessMergedBeanDefinition
InstantiationAwareBeanPostProcessor postProcessAfterlnstantiation
SmartInstantiationAwareBeanPostProcessor getEarlyBeanReference
BeanFactoryAware postProcessPropertyValues
ApplicationContextAwareProcessor invokeAwarelnterfaces
BeanNameAware setBeanName
InstantiationAwareBeanPostProcessor postProcessBeforelnstantiation|
@PostConstruct
InitializingBean afterPropertiesSet
FactoryBean getobject
SmartlnitializingSingleton afterSingletonslnstantiated
CommandLineRunner run
DisposableBeandestroy

源码分析

在Bean创建完成后,进行初始化的过程中,主要包含了初始化的前置、后置处理,以及初始化方法的调用。@PostConstruct注解将在applyBeanPostProcessorsBeforeInitialization这个前置处理

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//遍历了在spring启动过程中被注册的BeanPostProcessor接口,for (BeanPostProcessor processor : getBeanPostProcessors()) {//调用其前置方法。Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;
}

@PostConstruct注解是会被一个专门的BeanPostProcessor接口的具体实现类来处理的InitDestroyAnnotationBeanPostProcessor

//org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor@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;
}
public void invokeInitMethods(Object target, String beanName) throws Throwable {Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;Collection<LifecycleElement> initMethodsToIterate =(checkedInitMethods != null ? checkedInitMethods : this.initMethods);if (!initMethodsToIterate.isEmpty()) {for (LifecycleElement element : initMethodsToIterate) {if (logger.isTraceEnabled()) {logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());}//  调用element.invoke(target);}}
}

注意:在CommonAnnotationBeanPostProcessor这个后置处理器的构造方法中,@PostConstruct注解被设置为了initAnnotationType的值

//org.springframework.context.annotation.CommonAnnotationBeanPostProcessorpublic CommonAnnotationBeanPostProcessor() {setOrder(Ordered.LOWEST_PRECEDENCE - 3);setInitAnnotationType(PostConstruct.class);setDestroyAnnotationType(PreDestroy.class);ignoreResourceType("javax.xml.ws.WebServiceContext");// java.naming module present on JDK 9+?if (jndiPresent) {this.jndiFactory = new SimpleJndiBeanFactory();}
}

应用场景

@PostConstruct不算一个扩展点,但是也有比较实用的应用场景,主要在Servlet初始化之前加载一些缓存数据,比如

  • 数据字典,
  • 读取properties配置文件

代码示例

@Component
@Slf4j
public class TagPostConstruct {@Autowiredprivate TestAutowired testAutowired;public TagPostConstruct(){log.info("TagPostConstruct构造方法------run");}@PostConstructpublic void myPostConstruct() {log.info("PostConstruct------run");}
}@Slf4j
@Component
public class TestAutowired {public TestAutowired(){log.info("TestAutowired构造方法------run");}
}

运行示例

可以看出@PostConstruct注解在整个Bean初始化中执行的顺序:@Constructor(构造方法)-> @Autowired(依赖注入)-> @PostConstruct(注解的方法);
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com