1 @PostStruct

1.1 概述

定义及用途

@PostConstruct(javax.annotation.PostConstruct)注解好多人以为是Spring提供的。而实际上是Java自身的注解。

Java中该注解的说明:

@PostConstruct,该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。

PostConstruct构造函数之后执行,init()方法之前执行。

通常地,在Spring框架中也会使用到@PostConstruct注解。那么,整个Bean初始化的执行顺序为:

  • step1 Constructor(构造方法)
  • step2 @Autowired(依赖注入)
  • step3 @PostConstruct(注释的方法)

应用场景

  • 场景1:在静态方法中调用spring依赖注入Bean中的方法。
package com.example.studySpringBoot.util;

import com.example.studySpringBoot.service.MyMethorClassService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component
public class MyUtils {
private static MyUtils staticInstance = new MyUtils(); @Autowired
private MyMethorClassService myService; @PostConstruct
public void init(){
staticInstance.myService = myService;
} public static Integer invokeBean(){
return staticInstance.myService.add(10,20);
}
}

源码

package javax.annotation;

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

使用示例

1.2 发展历程:[JDK 1.6-1.8]

1.2.1 始于JDK1.6 Annotations

Common Annotations 原本是Java EE 5.0(JSR 244)规范的一部分,现在SUN把它的一部分放到了Java SE 6.0中。随着Annotation元数据功能加入到Java SE 5.0里面,很多Java 技术都会用Annotation部分代替XML文件来配置运行参数。以下列举Common Annotations 1.0里面的几个Annotations:

  • @Generated:用于标注生成的源代码

  • @Resource: 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于setter方法的注入两种方式 。

  • @Resources:同时标注多个外部依赖,容器会把所有这些外部依赖注入

  • @PostConstruct:标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为PostConstruct 。

  • @PreDestroy:当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为PreDestroy 作者:苦逼码农xisdn https://www.bilibili.com/read/cv7666575 出处:bilibili

1.2.2 弃于JDK1.9,止于JDK1.11

  • JDK 在Java 9中已被弃用,而在Java 11中已被删除

  • 解决方法:主动引入第三方JAR包

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>

1.3 原理分析

JDK提供的@PostConstruct注解,Spring是如何实现的呢?

需要先学习下BeanPostProcessor这个接口:

import org.springframework.beans.factory.config;
import ... public interface BeanPostProcessor { /**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
*
* 任何Bean实例化,并且Bean已经populated(填充属性) 就会回调这个方法
*
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
*
* 任何Bean实例化,并且Bean已经populated(填充属性) 就会回调这个方法
*
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

Spring初始化是那里回调这些方法呢?

AbstractApplicationContext.finishBeanFactoryInitialization(...);
beanFactory.preInstantiateSingletons();
DefaultListableBeanFactory.getBean(beanName);
AbstractBeanFactory.doGetBean();
AbstractAutowireCapableBeanFactory.createBean(....)
populateBean(beanName, mbd, instanceWrapper);
initializeBean(...)
//调用BeanPostProcessor.postProcessBeforeInitialization()方法
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//调用BeanPostProcessor.postProcessBeforeInitialization()方法
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

BeanPostProcessor有个实现类CommonAnnotationBeanPostProcessor,就是专门处理@PostConstruct、@PreDestroy注解。

CommonAnnotationBeanPostProcessor的父类InitDestroyAnnotationBeanPostProcessor()
InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()
InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata()
// 组装生命周期元数据
InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata()
// 查找@PostConstruct注释的方法
InitDestroyAnnotationBeanPostProcessor.initAnnotationType
// 查找@PreDestroy注释方法
InitDestroyAnnotationBeanPostProcessor.destroyAnnotationType
// 反射调用
metadata.invokeInitMethods(bean, beanName);

X 参考文献

[Java SE]JDK版本特性解读:@PostStruct[JDK1.6-JDK1.8]的更多相关文章

  1. Java SE 8 新增特性

    Java SE 8 新增特性 作者:Grey 原文地址: Java SE 8 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...

  2. Java SE 9 新增特性

    Java SE 9 新增特性 作者:Grey 原文地址: Java SE 9 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...

  3. Java SE 11 新增特性

    Java SE 11 新增特性 作者:Grey 原文地址:Java SE 11 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  4. Java SE 13 新增特性

    Java SE 13 新增特性 作者:Grey 原文地址:Java SE 13 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  5. Java SE 14 新增特性

    Java SE 14 新增特性 作者:Grey 原文地址:Java SE 14 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  6. Java SE 15 新增特性

    Java SE 15 新增特性 作者:Grey 原文地址:Java SE 15 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  7. Java SE 16 新增特性

    Java SE 16 新增特性 作者:Grey 原文地址:Java SE 16 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  8. Java SE 17 新增特性

    Java SE 17 新增特性 作者:Grey 原文地址:Java SE 17 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  9. Java SE 18 新增特性

    Java SE 18 新增特性 作者:Grey 原文地址:Java SE 18 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  10. Java SE 19 新增特性

    Java SE 19 新增特性 作者:Grey 原文地址: 博客园:Java SE 19 新增特性 CSDN:Java SE 19 新增特性 源码 源仓库: Github:java_new_featu ...

随机推荐

  1. 最短路算法之 Dijkstra

    部分内容参考了李煜东的<算法竞赛进阶指南>,在此声明. 单源最短路径 单源最短路径问题,是说,给定一张有向图(无向图)\(G=(V,E)\) ,\(V\) 是点集,\(E\) 是边集,\( ...

  2. Idea项目构建时解决方法

    java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: GC overhead limit exceeded 整 ...

  3. 如何配置php.ini才能让PHP性能最大优化

    用于生产环境中的PHP需要对其进行优化,可以让PHP自身发挥更好的性能,除了写好PHP代码,还要配置好php.ini.本文从内存.文件上传.会话缓冲输出.真实路径缓存这几个方面讲解php.ini的配置 ...

  4. php 验证身份证合法性

    function checkIdcard($num = '') { $length = strlen($num); if ($length == 15) { //如果是15位身份证 //15位身份证没 ...

  5. 【git入门】基于阿里云搭建git

    本文旨在说明基本的git使用流程,分为以下几个部分: 1.安装git环境 2.注册 3.git基本操作 一.安装git环境 第一次使用git,需要先安装配置git环境,windows版下载地址http ...

  6. 1008.Django模型基础03

    一.关系表的数据操作 关系表中的数据操作 查看数据库中的表结构 一对多表关系数据的添加: 1. 第一种方式就是跟之前一样,用传参的方法添加,需要注意的是外键的值必须是关联表中已存在的值: 2. 第二种 ...

  7. 帝国CMS 登录后跳转ecmsadmin.php 白页 多个解决方案

    帝国CMS 6.6 版本, 运维的网站查询除了问题, 把网站数据库和整体网站拷贝到本地服务器, 配置好 e/config/config.php    和 e/class/config.php 两个目录 ...

  8. Blog作业03

    目录 前言 设计与分析 踩坑心得 改进建议 总结 前言 这三次作业的题目只有2道题,但是在题量减小的同时,这三次作业集的难度也相应的上去了,题目的质量很好,运用很广泛,也考验了很多的知识点.这三次的作 ...

  9. openssl 全面支持国密SM2/SM3/SM4加密算法

    sm4展示 代码 /** 文件名: https://github.com/liuqun/openssl-sm4-demo/blob/cmake/src/main.c */ #include <s ...

  10. 使用loadrunner运行中问题(无代码生成解决方法)

    开始录制之后,不能成功录制,工具栏events一直是2,打开新网站不跳动,结束录制之后没有代码生成 进入软件,点击工具栏的录制,选择录制选项,将http高级如下设置 同时也要修改套接字,如下配置 当开 ...