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. (1)从txt读取GPS数据 真实GPS和slam定位GPS匹配 坐标系ecef和enu转化 计算均方根误差和单帧误差

    #!/usr/bin/python # -*- coding: UTF-8 -*- import numpy as np import os #==========================1坐 ...

  2. RabbitMq的部署(docker)和操作(python)详解

    一.简介: RabbitMq 是实现了高级消息队列协议(AMQP)的开源消息代理中间件.消息队列是一种应用程序对应用程序的通行方式,应用程序通过写消息,将消息传递于队列,由另一应用程序读取 完成通信. ...

  3. Mysql的MVCC与幻读

    以下特殊情况在可重复读时会产生幻读: 1.a事务先select,b事务insert确实会加一个gap锁,但是如果b事务commit,这个gap锁就会释放(释放后a事务可以随意操作), 2.a事务再se ...

  4. vue上传证书

    //队伍证书上传 getFile() { var that = this; // //1 创建formData let formData = new FormData(); // //2 添加数据,k ...

  5. springboot jodconverter openoffice 实现 office 文件 在线预览

    这个已是好几个月前做的,好多细节已记得不那边清楚了.今天部署到环境还遇到不少问题.总结下. 1.office 文件实现在线预览的一般思路就是,将文件转pdf,在通过pdf.js 实现在线浏览.这其中转 ...

  6. NOIP2008普及组

    T2]排座椅 横行相同时列数+1,纵行相同时行数+1. 主要是用桶排序,因为范围太大了,用sort会超时 #include<iostream> #include<cstring> ...

  7. 基于C语言的小学四则运算出题器

    一.实验目的: 1.帮助老师产出每周随机的300道含有两个运算符的四则运算,. 2.每次题目的产出均为随机,增强同学的四则运算能力. 二.实验环境: Visual C++ 三.实验内容: 1.实现随机 ...

  8. 解决Vue打包后背景图片路径错误问题(转)

    1.原因解析 当用vue-cli自动构建项目后,有两种运行方法,分别是: npm run dev : 提供一个开发的环境,自动热更新,资源使用绝对路径,所以可以正常看到背景图片. npm run bu ...

  9. mi-root

    1.解锁Bootloder 2.刷开发版系统[xposed最新支持8.1],Android版本相对应,线刷的时候一定要记得只选择"全部删除",不要选择"全部删除并lock ...

  10. button 样式 触发器

    <Style x:Key="Style.OkOperationButton" TargetType="ButtonBase"> <Setter ...