[Java SE]JDK版本特性解读:@PostStruct[JDK1.6-JDK1.8]
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程序员必备基础:JDK 5-15都有哪些经典新特性 - bilibili
- jdk6新特性 - 码农家园
- JDK新特性(JDK6) [转载] - 蜂巢驻点
- 无法在Java 11中使用@PostConstruct和@PostDestroy - CSDN 【推荐】
- Spring PostConstruct and PreDestroy Annotations - baeldung 【推荐】
[Java SE]JDK版本特性解读:@PostStruct[JDK1.6-JDK1.8]的更多相关文章
- Java SE 8 新增特性
Java SE 8 新增特性 作者:Grey 原文地址: Java SE 8 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...
- Java SE 9 新增特性
Java SE 9 新增特性 作者:Grey 原文地址: Java SE 9 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...
- Java SE 11 新增特性
Java SE 11 新增特性 作者:Grey 原文地址:Java SE 11 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 13 新增特性
Java SE 13 新增特性 作者:Grey 原文地址:Java SE 13 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 14 新增特性
Java SE 14 新增特性 作者:Grey 原文地址:Java SE 14 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 15 新增特性
Java SE 15 新增特性 作者:Grey 原文地址:Java SE 15 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 16 新增特性
Java SE 16 新增特性 作者:Grey 原文地址:Java SE 16 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 17 新增特性
Java SE 17 新增特性 作者:Grey 原文地址:Java SE 17 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 18 新增特性
Java SE 18 新增特性 作者:Grey 原文地址:Java SE 18 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 19 新增特性
Java SE 19 新增特性 作者:Grey 原文地址: 博客园:Java SE 19 新增特性 CSDN:Java SE 19 新增特性 源码 源仓库: Github:java_new_featu ...
随机推荐
- linux 中安装、更新和卸载软件
1.Aptitude aptitude 与 apt-get 一样,是 Debian 及其衍生系统中功能极其强大的包管理工具. 与 apt-get 不同的是,aptitude 在处理依赖问题上更佳一些. ...
- doy 19 进程管理
1.进程管理 1.什么是进程,什么是线程 1.什么是程序 一般情况下,代码,安装包等全部都是应用程序. 2.什么是进程 应用程序运行起来的能够提供某种服务的实例. 3.什么是线程 进程中处理具体事务 ...
- JS刷题自制参考知识
(建议复制到本地,需要看的时候打开Typora,大纲点击要查的内容即可,我一般记不清某个方法的时候就查一下.) 基础 Typescript TypeScript是一个开源的.渐进式包含类型的JavaS ...
- [Leetcode 111]二叉树的最短深度 BFS/DFS
题目 给定二叉树,求最短路径包含的节点个数 https://leetcode.com/problems/minimum-depth-of-binary-tree/ Given a binary tre ...
- Spring AOP @before@after@around@afterreturning@afterthrowing执行顺序
public Object aop(Method method,Object object) { try { try { /*doAround start*/ doBefore(); method.i ...
- Surge 开启脚本功能后,京东自动签到总结
本人小白,花费半天时间才弄好,写下这个给自己和后来人指路. Surge 开启脚本功能后,京东自动签到获取京豆总结: 1.注意 去 Raw 真实地址下载 js https://github.com/No ...
- uni-app微信小程序解决多个视频同时播放问题
这里我用的uni-app开发的小程序,微信小程序原生开发也是同理, 写法和api简单改下就行 当你的页面上有多个视频video组件标签时, 会出现多个视频可以同时播放的问题,这样显然是不正常的, 那么 ...
- Hive使用Tez作为计算引擎,hive启动报错
1.问题描述: (1)问题示例: 1)hive使用配置文件hive-site.xml配置tez为计算引擎,hive登录报错: [Hadoop@master Tmp]$ hiveHive Session ...
- python-实现动态web服务器
# encoding=utf-8 import socket from multiprocessing import Process import re import sys # 设置静态文件根目录 ...
- Linux下C语言程序的内存布局
在<虚拟地址空间以及编译模式>一节中讲到,虚拟地址空间在32位环境下的大小为 4GB,在64位环境下的大小为 256TB,那么,一个C语言程序的内存在整个地址空间中是如何分布的呢?数据在哪 ...