当前位置:首页 > 科技  > 软件

探索Spring Boot中@PostConstruct的魔法

来源: 责编: 时间:2023-12-08 09:14:28 183观看
导读前言@postContruct全限定类名是javax.annotation.PostConstruct,可以看出来其本身不是Spring定义的注解,但是Spring提供了具体的实现,所以这篇文章主要分析的是@PostConstruct在Spring项目开发中的功能特性、实现方式和

前言

@postContruct全限定类名是javax.annotation.PostConstruct,可以看出来其本身不是Spring定义的注解,但是Spring提供了具体的实现,所以这篇文章主要分析的是@PostConstruct在Spring项目开发中的功能特性、实现方式和基本工作原理。Tcg28资讯网——每日最新资讯28at.com

功能特性

从@PostConstruct注解的注释上看,可以了解到以下内容:Tcg28资讯网——每日最新资讯28at.com

1、要在依赖加载后,对象佤用前执行,并且只执行一次;Tcg28资讯网——每日最新资讯28at.com

2、所有支持依赖注入的类都需要支持此方法。即使类没有请求注入任何的资源,也必须调用被@PostConstruct注解标记的方法;Tcg28资讯网——每日最新资讯28at.com

3、一个类中在一个方法上使用@PostConstruct注解;Tcg28资讯网——每日最新资讯28at.com

4、使用@PostConstruct注解标记的方法不能有参数,除非是拦截器,可以采用拦截器规范定义的InvocationContext对象。Tcg28资讯网——每日最新资讯28at.com

5、使用@PostConstruct注解标记的方法不能有返回值,实际上如果有返回值,也不会报错,但是会忽略掉;Tcg28资讯网——每日最新资讯28at.com

6、使用@PostConstruct注解标记的方法的权限,public、private、protected都可以;Tcg28资讯网——每日最新资讯28at.com

7、使用@PostConstruct注解标记的方法不能被static修饰,但是final是可以的;Tcg28资讯网——每日最新资讯28at.com

package javax.annotation;import java.lang.annotation.*;import static java.lang.annotation.ElementType.*;import static java.lang.annotation.RetentionPolicy.*;@Documented@Retention (RUNTIME)@Target(METHOD)public @interface PostConstruct {}

但是在在实际的Spring项目中Bean的生命周期里,其执行的时机是:1、Bean的实例化;2、Bean内依赖属性的注入 ;3、Bean里被@PostConstruct标记的方法;Tcg28资讯网——每日最新资讯28at.com

下面在实现方式里,用一个小例子来验证一下这个过程;Tcg28资讯网——每日最新资讯28at.com

实现方式

1、定义一个ExampleController类,采用setter的依赖注入的方式,注入exampleService属性,另外在定义一个myPostConstruct方法用@PostConstruct注解标记;Tcg28资讯网——每日最新资讯28at.com

@RestController@Slf4jpublic class ExampleController {    private ExampleService exampleService;    public ExampleController() {        log.info("----ExampleController无参数构造方法被执行");    }    @Autowired    public void setExampleService(ExampleService exampleService) {        this.exampleService = exampleService;        log.info("----ExampleController类的setExampleService方法被调用");    }    @PostConstruct    public void myPostConstruct(){        log.info("----ExampleController类的myPostConstruct方法被调用");    }}

2、定义ExampleService类Tcg28资讯网——每日最新资讯28at.com

@Service@Slf4jpublic class ExampleService {    public ExampleService() {        log.info("----ExampleService的无参数构造方法被调用");    }}

3、定义一个单元测试,在单元测试中启动Spring容器;Tcg28资讯网——每日最新资讯28at.com

@Testpublic void test4(){    log.info("----单元测试执行开始");    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.fanfu");    log.info("----单元测试执行完毕");}

单元测试验证结果:Tcg28资讯网——每日最新资讯28at.com

图片图片Tcg28资讯网——每日最新资讯28at.com

从单元测试的执行结果来看,首先,ExampleConstroller被实例化,接着是ExampleService被实例化,然后通过setter依赖注入的方式把ExampleService对象注入到了ExampleConstroller对象中,之后才开始了被@PostConstruct注解标记的myPostConstruct方法的执行。下面就单元测试的结果分析一个@PostConstruct注解的工作原理。Tcg28资讯网——每日最新资讯28at.com

工作原理

@PostConstruct的工作原理的关键问题就是:在Spring容器启动的过程,被@PostConstruct标记的方法是怎么被执行的?Tcg28资讯网——每日最新资讯28at.com

在被@PostConstruct标记的方法上打上断点,待程序执行的断点的时候观察一下方法调用栈信息,这时会发现:Tcg28资讯网——每日最新资讯28at.com

1、Spring容器启动过程的最后一步,即把需要提前注册的一些非懒加载的单例Bean时,如ExampleController,注意这时exampleController对象实例化完成,需要注入的exampleService的属性已经被实例化,且已经注入到exampleController对象中,在BeanPostProcessor接口的扩展方法中,被@PostConstruct标记的方法开始触发执行,入口位置在AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization。Tcg28资讯网——每日最新资讯28at.com

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)      throws BeansException {   Object result = existingBean;   for (BeanPostProcessor processor : getBeanPostProcessors()) {      Object current = processor.postProcessBeforeInitialization(result, beanName);      if (current == null) {         return result;      }      result = current;   }   return result;}

图片图片Tcg28资讯网——每日最新资讯28at.com

那么触发被@PostConstruct注解标记的方法执行的BeanPostProcessor接口的具体是实现是哪个类呢?通过debug分析,是CommonAnnotationBeanPostProcessor类。Tcg28资讯网——每日最新资讯28at.com

图片图片Tcg28资讯网——每日最新资讯28at.com

2、CommonAnnotationBeanPostProcessor类继承于InitDestroyAnnotationBeanPostProcessor,实际的触发@PostConstruct标记方法执行的入口是在InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization()Tcg28资讯网——每日最新资讯28at.com

3、InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization()内,逻辑相对比较简洁,先查询bean中被@PostConstruct标记的方法,然后再使用java反射来执行这个方法;Tcg28资讯网——每日最新资讯28at.com

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    //查询bean中被@PostConstruct标记的方法,相关的信息封在LifecycleMetadata对象的    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());   try {    //使用java反射执行被@PostConstruct标记的方法      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;}

图片图片Tcg28资讯网——每日最新资讯28at.com

总结

从以上几步的分析来看,被@PostConstruct标记的方法是怎么被执行的,这个问题回答清楚了。如果面试官问你,你了解@PostContruct注解是怎么工作的吗?你就可以这么回答他:在Bean实例化、属性注入后,被@PostConstruct标记的方法是在BeanPostProcessor的扩展方法postProcessBeforeInitialization()触发执行的,具体实现类是InitDestroyAnnotationBeanPostProcessor,具体的逻辑是:先查询被@PostConstruct标记的方法,然后使用java反射去执行这个方法。回答完后,如果他不换一个问题的话,把Springboot的扩展点都给他盘一遍。Tcg28资讯网——每日最新资讯28at.com

Tcg28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-39509-0.html探索Spring Boot中@PostConstruct的魔法

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 设计之魅:高质量面向对象设计的秘密

下一篇: NUMA架构:CPU和内存性能瓶颈的终结者!

标签:
  • 热门焦点
  • 官方承诺:K60至尊版将会首批升级MIUI 15

    官方承诺:K60至尊版将会首批升级MIUI 15

    全新的MIUI 15今天也有了消息,在官宣了K60至尊版将会搭载天玑9200+处理器和独显芯片X7的同时,Redmi给出了官方承诺,K60至尊重大更新首批升级,会首批推送MIUI 15。也就是说虽然
  • 2023 年的 Node.js 生态系统

    2023 年的 Node.js 生态系统

    随着技术的不断演进和创新,Node.js 在 2023 年达到了一个新的高度。Node.js 拥有一个庞大的生态系统,可以帮助开发人员更快地实现复杂的应用。本文就来看看 Node.js 最新的生
  • 服务存储设计模式:Cache-Aside模式

    服务存储设计模式:Cache-Aside模式

    Cache-Aside模式一种常用的缓存方式,通常是把数据从主存储加载到KV缓存中,加速后续的访问。在存在重复度的场景,Cache-Aside可以提升服务性能,降低底层存储的压力,缺点是缓存和底
  • JavaScript学习 -AES加密算法

    JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 使用AIGC工具提升安全工作效率

    使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 中国家电海外掘金正当时|出海专题

    中国家电海外掘金正当时|出海专题

    作者|吴南南编辑|胡展嘉运营|陈佳慧出品|零态LT(ID:LingTai_LT)2023年,出海市场战况空前,中国创业者在海外纷纷摩拳擦掌,以期能够把中国的商业模式、创业理念、战略打法输出海外,他们依
  • 微博大门常打开,迎接海外画师漂洋东渡

    微博大门常打开,迎接海外画师漂洋东渡

    作者:互联网那些事“起猛了,我能看得懂日语了”。“为什么日本人说话我能听懂?”“中文不像中文,日语不像日语,但是我竟然看懂了”…&hell
  • 电博会与软博会实现

    电博会与软博会实现"线下+云端"的双线融合

    在本次“电博会”与“软博会”双展会利好条件的加持下,既可以发挥展会拉动人流、信息流、资金流实现快速交互流动的作用,继而推动区域经济良性发展;又可以聚
  • “买真退假” 这种“羊毛”不能薅

    “买真退假” 这种“羊毛”不能薅

    □ 法治日报 记者 王春   □ 本报通讯员 胡佳丽  2020年初,还在上大学的小东加入了一个大学生兼职QQ群。群主“七王”在群里介绍一些刷单赚
Top