[Java SE/JDK] 核心源码精讲:javax.annotation.PostStruct/@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

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

posted @ 2023-01-15 17:43  千千寰宇  阅读(307)  评论(0编辑  收藏  举报