【HBZ分享】FactoryBean的应用 与 BeanFactroyPostProcessor的应用 与 BeanPostProcesser的应用

news2025/2/3 8:09:20

FactoryBean的应用实战

  1. 需要写一个A类来实现FactoryBean
  2. 实现FactoryBean的3个方法,即getOject(), getObjectType(), isSingleton()
  3. 注意:在通过xml的【 】标签或者通过注解方式将A类注入容器的时候,返回的实例不是A类,而是T类,因为他会自动的执行getObject()方法,而getObject()方法中new的是T类的对象,所以这块不要搞错了
  4. 下面代码案例: 有xml配置可见,bean注入的是MyFactoryBean, 但图中可以看出实例出来的却是ObjectBean类型的,

implements FactoryBean代码:

package com.spring.factoryBean实战;
import org.springframework.beans.factory.FactoryBean;
public class myFactoryBean implements FactoryBean<ObjectBean> {
    @Override
    public ObjectBean getObject() throws Exception {
        return new ObjectBean("hbz", 26);
    }
    @Override
    public Class<?> getObjectType() {
        return null;
	}
}

xml配置文件代码:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id = "myFactoryBean"  class="com.spring.factoryBean实战.myFactoryBean"></bean>
</beans>

在这里插入图片描述

BeanFactroyPostProcessor的应用实战

  1. BeanFactroyPostProcessor 会在 BeanPostProcessor之前执行, 即先执行BeanFactroyPostProcessor
  2. 作用:读取应用程序上下文,并对其属性进行修改, 可以修改BeanDefinition中的属性,比如设置单例多例(setScope), 是否是懒加载(setLazyInit()), 动态设置初始化方法等
  3. 执行BeanFactroyPostProcessor时还没有进行指定类的初始化(还未执行构造函数),所以通过BeanFactroyPostProcessor可以改变目标类属性
  4. 代码实战:
    FactoryBeanPostPorcess代码:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFacotryPostProcess implements BeanFactoryPostProcessor {

    public MyBeanFacotryPostProcess() {
        System.out.println("构造函数执行--------------------------");
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

        // 获取所有的bean
        String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
        for(String befinitonName : beanDefinitionNames){
            if("productService".equalsIgnoreCase(befinitonName)){
                BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(befinitonName);
                // 单例多例
                beanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
                // 设置初始化方法
                beanDefinition.setInitMethodName("testInit");
            }
        }
    }
}

xml配置类代码:

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id = "productService"  class="com.spring.beanFactoryPostProcess实战.ProductServiceImpl" scope="singleton"></bean>

<!-- 这句需要加,表示启动的时候就注入到spring容器并运行一次, 这个类中就是设置ProductServiceImpl的属性的, 如果不写,那么动态配置的类属性是不会生效的-->
    <bean id = "myBeanFacotryPostProcess"  class="com.spring.beanFactoryPostProcess实战.MyBeanFacotryPostProcess"></bean>
</beans>

目标类代码:

package com.spring.beanFactoryPostProcess实战;

public class ProductServiceImpl implements ProductService{

    public ProductServiceImpl(){
        System.out.println("这个是构造函数");
    }

    @Override
    public void example() {
        System.out.println("类名: "+ this.getClass().toString());
    }


    public void testInit(){
        System.out.println("这个是初始化方法");
    }
}

输出结果:
在这里插入图片描述

BeanPostProcessor的应用

  1. BeanPostProcessor在BeanFactoryPostProcessor之后执行
  2. BeanPostProcessor作用于bean实例化过程中, 可以改变bean实例中的属性值, 比如bean中有个name = “123”, 则可以在BeanPostProcessor的两个实现方法中将其改成setName(“456”)
  3. BeanPostProcessor通常需要实现两个方法,分别是postProcessBeforeInitialization, postProcessAfterInitialization
  4. postProcessBeforeInitialization: 在目标类的【初始化方法】之前执行。postProcessAfterInitialization:在目标类【初始化方法之后】执行
  5. postProcessBeforeInitialization,postProcessAfterInitialization都会有个参数,叫【String beanName】, 这个beanName是容器中所有的bean(即容器有多少个bean,这俩方法就走多少遍),如果想在指定目标类触发BeanPostProcessor,则需要加一个判断。如果在xml定义了bean,则使用xml中定义的name去和beanName作比较,如果不是在xml中定义的,是new出来的,直接用目标类的【类名(首字母小写)】去和beanName比较,默认new出来的beanName就等于类名首字母小写
  6. 代码:

BeanPostProcessor实现类:

package com.spring.beanPostProcessor实战;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     * 在每个bean初始化方法之前执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        System.out.println("MyBeanPostProcessor # BeforeInitialization 调用 beanName = " + beanName);
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    /**
     * 在每个bean初始化方法之后执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        System.out.println("MyBeanPostProcessor # AfterInitialization 调用 beanName = " + beanName);
        
        // 判断beanName,如果beanName = productBeanService, 则就执行如下操作
        if("productBeanService".equalsIgnoreCase(beanName)){
            ProductBeanServiceImpl productBeanService = (ProductBeanServiceImpl) bean;
            productBeanService.setName("v2.修改后的值");
            BeanPostProcessor.super.postProcessAfterInitialization(productBeanService, beanName);
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

xml配置代码:

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id = "productBeanService"  class="com.spring.beanPostProcessor实战.ProductBeanServiceImpl" scope="singleton" init-method="testInit"></bean>

    <bean id = "myBeanPostProcessor"  class="com.spring.beanPostProcessor实战.MyBeanPostProcessor"></bean>
</beans>

目标类代码:

package com.spring.beanPostProcessor实战;

import org.springframework.beans.factory.InitializingBean;


/**
 * 实现InitializingBean就可以实现初始化方法,因为InitializingBean中的afterPropertiesSet就是初始化方法,无需通过xml指定
 */
public class ProductBeanServiceImpl implements ProductBeanService, InitializingBean {

    private String name = "v1.修改之前的值";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ProductBeanServiceImpl(){
        System.out.println("这个是构造函数");
    }

    @Override
    public void example() {
        System.out.println("类名: "+ this.getClass().toString());
    }

    /**
     * BeanPostProcessor中的postProcessBeforeInitialization方法会在该初始化方法之前执行
     * BeanPostProcessor中的postProcessAfterInitialization方法会在该初始化方法之后执行
     *
     */
    public void testInit(){
        System.out.println("这是在xml或者BeanFactoryPostProcess中指定的初始化方法");
    }

    /**
     * 这个也是初始化方法,但必须实现InitializingBean
     * 效果: 和testInit()一摸一样,该方法不需要在xml中配置,而testInit需要在xml或者通过BeanFactoryPostProcess配置并指定testInit初始化方法才可以
     *
     *
     * BeanPostProcessor中的postProcessBeforeInitialization方法会在该初始化方法之前执行
     * BeanPostProcessor中的postProcessAfterInitialization方法会在该初始化方法之后执行
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("这是InitializingBean的初始化方法");
    }
}

启动类代码:

package com.spring.beanPostProcessor实战;

import com.spring.beanFactoryPostProcess实战.ProductServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {

        // 读取指定的配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:beanPostPorcessor.xml");
        ProductBeanServiceImpl productBeanService = (ProductBeanServiceImpl) context.getBean("productBeanService");
        System.out.println(productBeanService);
    }
}

执行结果截图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/648174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML 基础

目录 HTML 结构 1.认识 HTML 标签 HTML 文件基本结构 标签层次结构 HTML 常见标签 注释标签 标题标签: h1-h6 段落标签: p 换行标签: br 格式化标签 图片标签: img 关于目录结构: 超链接标签: a 链接的几种形式: 表格标签 合并单元格 列表标签 表单标签 form …

【头歌-Python】Python第九章作业(初级)第 1、2、4 关

第1关&#xff1a;绘制温度曲线 任务描述 附件中是某月每天的最高温度和最低温度数据&#xff0c;请绘制本月的高温曲线&#xff08;红色、圆点标记坐标&#xff09;和低温曲线&#xff08;蓝色、星号标记坐标&#xff09;&#xff0c;线型、刻度如输出示例所示&#xff0c;线…

Rust每日一练(Leetday0031) 解码方法、复原 IP 地址

目录 91. 解码方法 Decode Ways &#x1f31f;&#x1f31f; 93. 复原 IP 地址 Restore IP Addresses &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 91. …

chatgpt赋能python:Python如何求平均

Python如何求平均 Python是一种非常流行的编程语言&#xff0c;它被广泛应用于各种领域&#xff0c;包括科学计算、数据分析、Web开发等。在这篇文章中&#xff0c;我们将介绍如何使用Python求平均值。 什么是平均数 平均数&#xff0c;也称为均值&#xff0c;是指一组数据的…

chatgpt赋能python:Python怎么求平均值?全面解析平均值计算方法

Python怎么求平均值&#xff1f;全面解析平均值计算方法 作为一种简洁易用的计算机编程语言&#xff0c;Python的应用范围已经越来越广泛。在Python中&#xff0c;我们可以轻松地进行各种统计和计算工作&#xff0c;其中求平均值是最常见的计算之一。在本文中&#xff0c;我们…

Redis过期策略

Redis 使用的过期删除策略是什么&#xff1f; Redis 是可以对 key 设置过期时间的&#xff0c;因此需要有相应的机制将已过期的键值对删除&#xff0c;而做这个工作的就是过期键值删除策略。 每当我们对一个 key 设置了过期时间时&#xff0c;Redis 会把该 key 带上过期时间存…

Redis 持久化-RDB和 持久化-AOF 的详细介绍以及区别

Redis 持久化-RDB 官方资料 在线文档: https://redis.io/topics/persistence 持久化方案 RDB&#xff08;Redis DataBase&#xff09; AOF&#xff08;Append Of File&#xff09; RDB 是什么? 在指定的时间间隔内将内存中的数据集快照写入磁盘&#xff0c; 也就Snapsh…

java中获取配置文件路径中含有中文,出现乱码的情况解决方案

问题背景&#xff1a;读取配置文件&#xff0c;但是读到的目录信息是中文乱码的。 第一步&#xff1a; 参考代码如上截图&#xff0c;方法即&#xff1a;读取jdbc配置&#xff0c;获取了配置文件&#xff08;jdbc.properties&#xff09;地址&#xff0c;然后加载这个文件读取…

chatgpt赋能python:Python中如何消除空格:从基础操作到高级技巧

Python中如何消除空格&#xff1a;从基础操作到高级技巧 Python是一种广泛使用的编程语言&#xff0c;深受许多工程师和开发者的喜爱。其中一个有用的技巧是如何消除字符串中的空格&#xff0c;特别是在处理和分析文本时。在本文中&#xff0c;我们将介绍三种不同的方法来解决…

springboot+vue+java学生选课成绩系统awwm9

主要内容&#xff1a; (1) 系统用户由三类组成&#xff1a;教师、学生和管理员 (2) 管理员负责的主要功能&#xff1a; 1. 用户进入登录界面&#xff0c;输入用户名&#xff0c;密码&#xff0c;选择管理员用户类型&#xff0c;然后点击“登录”按钮&#xff0c;后台验证…

Linux系统:stress-ng测压工具

目录 一、理论 1.stress工具简介与安装 2.语法及参数 3.具体安装 二、实验 1.运行8 cpu, 4 fork, 5 hdd, 4 io, 50 vm, 10小时 2.CPU测试 3.内存测试 4.IO测试 5.磁盘及I/O测试 三、问题 1. -bash: ./configure: 没有那个文件或目录 2. 下载yum源报错&#xff1a;未…

读发布!设计与部署稳定的分布式系统(第2版)笔记03_让系统稳定运行

1. 概念 1.1. 事务 1.1.1. 系统处理的抽象工作单元 1.1.1.1. 与数据库事务不同 1.1.1.2. 单个工作单元可能包含许多数据库事务 1.1.2. 系统存在的原因 1.1.2.1. 如果一个系统只能处理一种事务&#xff0c;那么它就是专用系统 1.1.2.2. 混合工作负载是系统能处理的不同事…

从 Google 删库,到蚂蚁跑路,Care 与 Fear 点燃的 Flare

Bytebase 第一次完成融资后写了一篇文章&#xff0c;主要讲了从行业层面做 Bytebase 的逻辑。一年过去了&#xff0c;这一年我们所处的开源/infra/数据库/企业服务赛道从热点归于平静&#xff0c;尤其在国内&#xff0c;又习惯性地反应过度&#xff0c;直接降到冰点。但从全球来…

学习PLC时为什么要学习上位机?

PLC是一种常用于工业自动化控制系统的设备。它用于监控和控制各种机器和过程&#xff0c;以实现自动化和优化生产。 学习PLC的过程中&#xff0c;了解和学习上位机是非常重要的。上位机是与PLC连接的计算机&#xff0c;它可以通过特定的软件与PLC进行通信、监控和控制。 以下…

【RabbitMQ教程】第七章 —— RabbitMQ - 发布确认高级

&#x1f4a7; 【 R a b b i t M Q 教程】第七章—— R a b b i t M Q − 发布确认高级 \color{#FF1493}{【RabbitMQ教程】第七章 —— RabbitMQ - 发布确认高级} 【RabbitMQ教程】第七章——RabbitMQ−发布确认高级&#x1f4a7; &#x1f337; 仰望天空&#xff0c…

分布式ID解决方案

常用的分布式 ID 的设计方案有哪些&#xff1f;Snowflake 是否受冬令时切换影响&#xff1f; 典型回答 首先&#xff0c;我们需要明确通常的分布式 ID 定义&#xff0c;基本的要求包括&#xff1a; 全局唯一&#xff0c;区别于单点系统的唯一&#xff0c;全局是要求分布式系…

NLP——Information Extraction信息提取

文章目录 Information Extraction 步骤Named Entity Recognition (NER)Typical Entity Tags 典型实体标签IO taggingIOB tagging神经网络做 NER Relation ExtractionRule-basedSupervised Relation ExtractionSemi-supervisedSemantic Drift 语义漂移Distant supervision 远程监…

chatgpt赋能python:在Python中添加NumPy

在Python中添加NumPy Python是一种功能强大且广泛使用的编程语言。它被广泛用于数据科学、人工智能和机器学习等领域。NumPy是一种用于数学和科学计算的Python库。本文将介绍在Python中如何添加NumPy库。 什么是NumPy? NumPy是一个开源的Python库&#xff0c;它提供了大量的…

ROCKETMQ极简介绍,顺序,事务示例

整体架构 Name Server 管理Broker实例的注册&#xff0c;提供心跳检测机制 路由管理&#xff1a; Producer和Conumser通过NameServer可以获取整个Broker集群的路由信息 生产者 Producer 以生产者组的形式出现&#xff0c;一个生产者组可以同时发送多个主题的消息 Broker …