注解@PostConstruct分析
作用
1.注解@PostConstruct可以添加在类的方法上面,如果这个类被IOC容器托管,那么在对Bean进行初始化前的时候会调用被这个注解修饰的方法
被定义在哪里?
1.被定义在了CommonAnnotationBeanPostProcessor类,这个类是InitDestroyAnnotationBeanPostProcessor类的子类,也实现了InstantiationAwareBeanPostProcessor接口(BeanDefinition的后置处理接口)。代码展示:
- public CommonAnnotationBeanPostProcessor() {
- setOrder(Ordered.LOWEST_PRECEDENCE - 3);
- setInitAnnotationType(PostConstruct.class);
- setDestroyAnnotationType(PreDestroy.class);
- ignoreResourceType("javax.xml.ws.WebServiceContext");
- }
2.故在这个CommonAnnotationBeanPostProcessor类实例化的时候注解就会被定义下来。
在何处被扫描?
1.在BeanDefinition的后置处理时调用 postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)进行扫描
2.在初始化前中调用处理器InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization方法进行扫描
汇总:
两处扫描的本质都是调用了 LifecycleMetadata findLifecycleMetadata(Class<?> clazz)方法(位于InitDestroyAnnotationBeanPostProcessor类里面),
扫描方法分析
1.findLifecycleMetadata方法分析:
说明:
1)判断缓存有没有构建,没有构建则调用构建Metadata对象的方法
2)缓存构建了,就去缓存里面寻找,没找到就调用构建Metadata对象的方法,把拿回来的对象存入缓存中
代码展示:
- private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
- if (this.lifecycleMetadataCache == null) {
- return buildLifecycleMetadata(clazz);
- }
- LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
- if (metadata == null) {
- synchronized (this.lifecycleMetadataCache) {
- metadata = this.lifecycleMetadataCache.get(clazz);
- if (metadata == null) {
- metadata = buildLifecycleMetadata(clazz);
- this.lifecycleMetadataCache.put(clazz, metadata);
- }
- return metadata;
- }
- }
- return metadata;
- }
2.buildLifecycleMetadata方法分析:
说明:
1)主要应用类反射机制的概念,doWithLocalMethods通过类获取所有方法,然后利用反射机制构建调用对象
2)LifecycleMetadata对象便是包含了该类的所有的初始化方法和销毁方法
代码展示:
- private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
- List<LifecycleElement> initMethods = new ArrayList<>();
- List<LifecycleElement> destroyMethods = new ArrayList<>();
- Class<?> targetClass = clazz;
- do {
- final List<LifecycleElement> currInitMethods = new ArrayList<>();
- final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
- //doWithLocalMethods,深入源码其实可知是通过类对象取出所有的方法,逐一进行调用lambda表达式的方法
- ReflectionUtils.doWithLocalMethods(targetClass, method -> {
- //判断初始化方法
- if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
- LifecycleElement element = new LifecycleElement(method);
- currInitMethods.add(element);
- }
- //判断销毁方法
- if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
- currDestroyMethods.add(new LifecycleElement(method));
- }
- });
- //根据继承关系故会有父类要比子类先构造,子类要比父类先销毁
- //所以这里采用头插法
- initMethods.addAll(0, currInitMethods);
- //这里会往末尾存放
- destroyMethods.addAll(currDestroyMethods);
- //寻找父类
- targetClass = targetClass.getSuperclass();
- }
- while (targetClass != null && targetClass != Object.class);
- return new LifecycleMetadata(clazz, initMethods, destroyMethods);
- }
在何处被调用?(过程分析)
1.既然是在初始化前的处理器中调用,而且源于InitDestroyAnnotationBeanPostProcessor这个处理器会在初始化前这个步骤中执行@PostConstruct的方法
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- //这一步是寻找
- LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
- try {
- //这一步是调用
- metadata.invokeInitMethods(bean, beanName);
- }
- catch (InvocationTargetException ex) {
- throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
- }
- catch (Throwable ex) {
- throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
- }
- return bean;
- }
2.基于反射机制调用方法对象来调用类对象的方法:
- public void invokeInitMethods(Object target, String beanName) throws Throwable {
- Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
- Collection<LifecycleElement> initMethodsToIterate = (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
- if (!initMethodsToIterate.isEmpty()) {
- for (LifecycleElement element : initMethodsToIterate) {
- element.invoke(target);
- }
- }
- }
- postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
注解@PostConstruct分析的更多相关文章
- 【JPA】注解@PostConstruct、@PreDestroy
从Java EE5规范开始,Servlet增加了两个影响Servlet生命周期的注解@PostConstruct和@PreConstruct.这两个注解被用来修饰一个非静态的void()方法,而且这个 ...
- uboot-的start.S详细注解及分析
原文地址:uboot-的start.S详细注解及分析 作者:zhouyg11 大多数bootloader都分为stage1和stage2两部分,u-boot也不例外.依赖于CPU体系结构的代码(如设备 ...
- Spring注解@PostConstruct与@PreDestroy
关于在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种: 第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作 第二 ...
- servlet注解@PostConstruct与@PreDestroy
从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion):@PostConstruct和@PreDestroy.这两个注解被用来修饰一个非静态的vo ...
- 注解@PostConstruct与@PreDestroy讲解及实例
从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion):@PostConstruct和@PreDestroy.这两个注解被用来修饰一个非静态的vo ...
- 注解@PostConstruct与@PreDestroy 特性说明
简介 Java EE5 引入了@PostConstruct和@PreDestroy这两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作.此文主要说明@PostCons ...
- Spring 注解详细分析解释有实例
概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...
- springboot - Constructor、@Autowired、@PostConstruct分析
1.Constructor 构造方法 2.@Autowired 依赖注入 3.@PostConstruct 在依赖注入完成后被自动调用 4. 三者的顺序: 从依赖注入的字面意思就可以知道,要将对象p注 ...
- 注解@PostConstruct与@PreDestroy详解及实例
Java EE5 引入了@PostConstruct和@PreDestroy这两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作.此文主要说明@PostConstru ...
随机推荐
- Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现
我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...
- NC15163 逆序数
NC15163 逆序数 题目 题目描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数.比如一个序列为 \ ...
- 当在命令行输入"pip install xxx"
当输入"pip install xxx"时发生了什么 不知道你在下载一些包的时候有没有什么疑惑,输入了"pip install xxx" ,系统是如何找到对应的 ...
- Tapdata 实时数据融合平台解决方案(五):落地
作者介绍:TJ,唐建法,Tapdata 钛铂数据 CTO,MongoDB中文社区主席,原MongoDB大中华区首席架构师,极客时间MongoDB视频课程讲师. 通过前面几篇文章,我们从企业数据整合与分 ...
- Graph-Based Social Relation Reasoning
title: Graph-Based Social Relation Reasoning, 2020 task: we propose a simpler, faster, and more accu ...
- Python语法糖,提升编程幸福感!!!
转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/a52bc938.html 大家好,我是测试蔡坨坨. 今天,我们来盘点一下Python中的那些语法糖. 什么是语法糖?语法糖不 ...
- 云ATM架构设计
云ATM架构设计 启动程序(Start.java) public class Start { public static void main(String[] args) { MainView vie ...
- idea 内置tomcat jersey 跨服务器 上传文件报400错误
报错内容 com.sun.jersey.api.client.UniformInterfaceException: PUT http://.jpg returned a response status ...
- 2022-07-13 第六组 润土 Java01学习笔记
1.数据类型: 基本数据类型: 整型: byte 字节型 -128-127 1个字节 short 短整型 2个字节 int 整型 4个字节 long 长整型 8个字节 浮点型: float 单精度 4 ...
- Solution -「HNOI2013」消毒
弱化一下,先考虑在二维上解决问题. 题目就转化为:有 \(n\) 个点 \((i, j)\) 需要被覆盖,而我们每次可以选一行或一列去覆盖,求覆盖所有点的最少选择次数. 如果我们对于每一个 \((i, ...