首页 > 编程语言 >[Java SE] JDK版本特性解读:@PostStruct[JDK1.6-JDK1.8]

[Java SE] JDK版本特性解读:@PostStruct[JDK1.6-JDK1.8]

时间:2023-01-15 17:57:30浏览次数:65  
标签:JDK1.8 Java JDK PostConstruct bean import 方法 annotation

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 参考文献

标签:JDK1.8,Java,JDK,PostConstruct,bean,import,方法,annotation
From: https://www.cnblogs.com/johnnyzen/p/17053824.html

相关文章

  • java.math.BigDecimal cannot be cast to java.lang.Float
    大致意思:BigDecimal类型不能直接强行转换成Float类型当我用FlinkCDC监听数据库,对获取到的数据进行转换计算时,发生了这个报错,下面是我的代码Floatrating=(Float)value......
  • JAVA线程池 submit方法返回值
    JAVA线程池submit方法返回值AbstractExecutorServicepublicabstractclassAbstractExecutorServiceimplementsExecutorService{//RunnableFuture是用于......
  • 12.(结构型模式)java设计模式之享元模式
    一、什么是享元模式Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意。享元模式是对象的结构......
  • 第一个 Java 程序
    本节我们将以 Windows 操作系统为例,编写并执行第一个 J**a 程序。在这之前,请确保你的操作系统上已经安装了JDK1.编译程序大家可能有个疑问,为什么需要编译程序呢?计......
  • Java入门关于JDK
    Java入门JDKJDK:JavaDevelopmentKitJDK是JavaDevelopmentKit的缩写,是Java的开发工具包。JDK:JavaDevelopmentToolKit(Java开发工具包)。JDK是整个JAVA的核心,包......
  • Error:java: Compilation failed: internal java compiler error 解决办法
    编译时提示错误 Error:java:Compilationfailed:internaljavacompilererror 1、查看项目的jdk(Ctrl+Alt+shift+S)File->ProjectStructure->ProjectSettings->......
  • Linux下JDK和Tomcat安装
    下载地址​​​http://www.oracle.com/technetwork/java/javase/downloads/index.html​​​http://download.oracle.com/otn-pub/java/jdk/8u31-b13/jdk-8u31-linux-......
  • JAVASE基础强化Day2
    总结:数据类型:基本数据类型,引用数据类型八大基本数据类型:Byte:字节类型:1个字节,8个bit,在内存中开辟8个bit的空间每个bit就是二进制的 Short:2个字节,8*2=16个bit,在内存中......
  • 哪种编程语言更适合编写Selenium Web驱动程序脚本,Python还是Java?
    在本文中,我们将学习哪种编程语言更适合编写SeleniumWeb驱动程序脚本,Python或Java。从选项池中选择理想的编程语言可能很困难。Python,Java和Selenium都有自己的一套功能。越......
  • Javascript脚本运算符执行顺序对照表
    Javascript脚本运算符执行顺序对照表:在线查看Javascript脚本运算符执行优先级别 ​​窍门:Ctrl+F快速查找​​Javascript脚本运算符优先级,是描述在计算机计算表达式时执行......