Spring后处理器-BeanPostProcessor

2023-09-21 13:16:19

Spring后处理器-BeanPostProcessor

  • Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过bean的初始化过程((该后处理器的执行时机)),例如:属性的填充、初始化方法init的执行等,其中有一个对外拓展的点BeanPostProcessor,我们称之为bean后处理器。与上文bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的BeanPostProcessor(即在配置文件中对其进行配置),会在流程节点上被Spring自动调用。
  • BeanPostProcessor接口代码如下
    • //
      // Source code recreated from a .class file by IntelliJ IDEA
      // (powered by FernFlower decompiler)
      //
      
      package org.springframework.beans.factory.config;
      
      import org.springframework.beans.BeansException;
      import org.springframework.lang.Nullable;
      
      public interface BeanPostProcessor {
          @Nullable
          default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              return bean;
          }
      
          @Nullable
          default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              return bean;
          }
      }
      
  • 创建实现该接口(BeanPsotProcessor)的类,要在配置文件中进行管理
    • 快捷键 ctrl + insert 重写接口方法
    • package com.example.PostProcessor;
      
      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.BeanPostProcessor;
      
      public class MyBeanPostProcessor implements BeanPostProcessor {
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              System.out.println(beanName + ":postProcessBeforeInitialization");
              return bean;
          }
      
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              System.out.println(beanName + ":postProcessAfterInitialization");
              return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
          }
      }
      
  • 测试类代码

    • package com.example.Test;
      
      
      import com.example.Service.Impl.UserServiceImpl;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      public class TestApplicationContext {
          public static void main(String[] args) {
              ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
              System.out.println(context.getBean(UserServiceImpl.class));
          }
      }
      
  • 运行结果如下


    •  

    • 展示了该后处理器的执行时机 


Before和After执行时机

  • 在Bean实例化过程可以配置相关对于bean对象的操作方法,具体间往期文章:Bean的配置- CSDN搜索
  • 注册为bean的类
    • package com.example.Service.Impl;
      
      import com.example.DAO.UserDAO;
      import com.example.Service.UserService;
      import org.springframework.beans.factory.InitializingBean;
      
      import java.util.List;
      import java.util.Map;
      import java.util.Set;
      
      
      public class UserServiceImpl implements UserService, InitializingBean {
          // todo 无参构造方法
          public UserServiceImpl() {
              System.out.println("UserServiceImpl实例化");
          }
      
          // todo 自定义初始化方法
          public void init() {
              System.out.println("自定义初始化方法init()");
          }
      
          @Override
          public void afterPropertiesSet() throws Exception {
              System.out.println("属性设置之后执行afterPropertiesSet()");
          }
      
      }
      
  • 实现bean后处理器的类
    • package com.example.PostProcessor;
      
      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.BeanPostProcessor;
      
      public class MyBeanPostProcessor implements BeanPostProcessor {
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              System.out.println(beanName + ":postProcessBeforeInitialization");
              return bean;
          }
      
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              System.out.println(beanName + ":postProcessAfterInitialization");
              return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
          }
      }
      
  • 配置文件

    • <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
          <bean class="com.example.PostProcessor.MyBeanPostProcessor"></bean>
          <bean id="userService" class="com.example.Service.Impl.UserServiceImpl" init-method="init">
      </beans>
  • 测试类

    • package com.example.Test;
      
      
      import com.example.Service.Impl.UserServiceImpl;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      public class TestApplicationContext {
          public static void main(String[] args) {
              ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
              System.out.println(context.getBean(UserServiceImpl.class));
          }
      }
      
  • 运行结果

小结 

  • 从上述运行结果来看,首先完成bean对象的创建,然后执行后处理器中的before方法,然后执行属性设置之后的方法,然后执行自定义的初始化方法,最后执行后处理器的after方法

案例

  • 对Bean方法进行执行时间日志增强
  • 要求
    • Bean的方法执行之前控制台打印当前时间
    • Bean的方法执行之后控制台打印当前时间
  • 分析
    • 对方法进行增强主要就是代理设计模式和包装设计模式
    • 由于Bean方法不确定,所以使用动态代理在运行期间执行增强操作
    • 在Bean实例创建完毕之后,进入到单例之前,使用Proxy真实的目标bean
更多推荐

学习vue3源码

🎬岸边的风:个人主页🔥个人专栏:《VUE》《javaScript》⛺️生活的理想,就是为了理想的生活!目录1.为什么要学习源码阅读优秀的代码的目的是让我们能够写出优秀的代码不给自己设限,不要让你周围人的技术上限成为你的上限功利性的阅读源码2.源码应该怎么阅读单点突破系统阅读具体方案3.本地怎么调试源码最后1.为什么

【微信小程序开发】宠物预约医疗项目实战-注册实现

【微信小程序开发】宠物预约医疗项目实战-注册实现第二章宠物预约医疗项目实战-注册实现文章目录【微信小程序开发】宠物预约医疗项目实战-注册实现前言一、打开项目文件二、编写wxss代码2.1什么是wxss2.2配置主程序全局样式三.在sign文件下的wxml文件中编写如下代码并保存四.sign.js文件代码编写如下4.1j

【Redis】深入探索 Redis 的数据类型 —— 无序集合 Set

文章目录一、Set类型介绍二、Set类型相关命令2.1添加元素和检查成员2.2移除元素2.3集合运算求交集求并集求差集2.4Set相关命令总结三、Set类型编码方式四、Set使用场景一、Set类型介绍Set(集合)是Redis数据库中的一种数据类型,它是一种无序的、不重复的数据结构,用于存储一组唯一的元素。Set在Re

【PyTorch 攻略 (4/7)】张量和梯度函数

一、说明W在训练神经网络时,最常用的算法是反向传播。在该算法中,参数(模型权重)根据损失函数相对于给定参数的梯度进行调整。损失函数计算神经网络产生的预期输出和实际输出之间的差异。目标是获得尽可能接近零的损失函数的结果。反向传播算法通过神经网络向后遍历,以调整权重和偏差以重新训练模型。这种随着时间的推移重新训练模型的来回

Word2Vec的原理是什么,如何用训练Word2Vec

Word2Vec是一种基于神经网络的词向量生成模型,通过训练预测上下文单词或中心单词来生成词向量。它包含两种不同的架构:跳字模型(Skip-gram)和连续词袋模型(ContinuousBag-of-Words,CBOW),它们在训练方式和结果表现上略有不同。1跳字模型(Skip-gram):在跳字模型中,模型的目标是

ES7新特性深度解析:提升JavaScript开发效率的利器

前言ES7(ECMAScript2016)是JavaScript的最新版本,引入了一些强大的新特性,旨在提升开发者的工作效率。本篇博客将深度解析ES7的一些重要特性,并且以不超过50%的代码比例展示其用法。包含属性初始化器的类(Class)定义ES7允许我们在类的定义中直接初始化属性,而不需要在constructor中

Docker镜像:构建、推送和创建多个容器实例

文章目录步骤1:构建自定义Docker镜像步骤2:推送和拉取Docker镜像步骤3:创建多个容器实例结论🎈个人主页:程序员小侯🎐CSDN新晋作者🎉欢迎👍点赞✍评论⭐收藏✨收录专栏:云计算✨文章内容:Docker镜像🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗Docke

PX4自动控制中常用的几个话题

订阅话题1、/mavros/state订阅/发布:订阅功能:订阅mavros的一些状态数据,如连接状态、是否解锁、当前无人机模式数据类型:mavros_msgs/StatestringMODE_PX4_MANUAL=MANUALstringMODE_PX4_ACRO=ACROstringMODE_PX4_ALTITUD

处理SQLSyntaxErrorException异常:数据库表 ‘books‘ 不存在;

目录背景介绍我的问题中的解决方法通用方法背景介绍今天遇见了这个问题,解决后发出来分享一下Java应用程序中的SQLSyntaxErrorException:表'bookmanagement.books'不存在问题解决解决MySQL错误:无法找到表'bookmanagement.booksjava.sql.SQLSynt

从数据、产品、管理的视角探讨MES管理系统

MES生产管理系统在企业生产中扮演着关键角色,它集成了生产流程、数据应用、管理功能等多方面要素,为企业提供全面的生产运营支持。本文将从数据的视角聊聊MES管理系统,介绍其在数据管理、分析和利用方面的应用;从产品的视角,剖析其在生产过程管理、质量控制和追溯能力等方面的功能;最后从管理的视角,阐述其在生产调度、资源管理和决

KVCache原理简述

在GPT的推理过程中,它根据完整的提问和回答的已生成部分,来生测下一个词(的概率)。例如,我们的提问是【天王盖地虎,】,回答是【宝塔镇河妖。】。那么第一次,GPT根据【天王盖地虎,】生成【宝】,之后根据【天王盖地虎,宝】生成【塔】,以此类推,直到碰上终止符。这里面提问【天王盖地虎,】的QKV实际上重复计算了很多遍。由于

热文推荐