详解Spring中BeanPostProcessor在Spring工厂和Aop发挥的作用

😉😉 学习交流群:

✅✅1:这是孙哥suns给大家的福利!

✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料

🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取!

🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

💞💞5:以上内容,进群免费领取呦~ 💞💞💞💞

一:BeanPostProcessor分析

1:BeanPostProcessor对于Spring工厂作用

        这个事后置处理Bean,这个东西的全称叫做BeanPostProcessor,最主要的作用是对Spring创建的对象进行再加工,这个是Spring工厂中的一个非常有用的高级特性,在Spring底层很多高级的封装的时候都有这个技术的影子,讲了Aop底层的实现的时候,会发现这个技术的价值是非常高的,Spring的Aop底层实现很大的一部分是这个技术进行支撑。

        BeanPostProcessor是对Spring的bean工厂进行在加工,Spring工厂创建对象的过程是:Spring获取Spring的核心配置文件之后对spring的核心配置文件进行解析,获取到响应的bean标签会后,通过反射技术调用该类的构造方法,创建该类的实例,第二件事是spring对这个类中的成员变量按照配置进行注入,注入完成之后,调用这个类的初始化方法,对这个类进行一个初始化,这个初始化方法是我们自己定义的,经过这样的一个过程,这个对象就创建并初始化好了,现在就可以通过getBean通过id进行获取这个对象,而这个后置处理bean,是在工厂创建完成这个对象之后,对这个对象进行再次加工,这就是这门技术的意义,那么她是怎么实现对这个工厂创建出来的对象进行再次加工的呢?BeanPostProcessor是一个接口,我们需要把这个对象加工的内容写到接口实现类对应的方法中即可。

        在这个接口当中呢有两两个方法,第一个方法是postProcessBeforeInitialization,另外的方法叫after,,这样的接口,当Bean实现了这个接口之后,spring在创建这个对象的过程中,在spring完成调用构造方法创建实例,并依据配置进行注入之后,spring就会调用这个类的postProcessBeforeIntitialzation方法进行一个初始化操作,是通过这个方法中的第一个Object类型bean参数进行传递的,另外一个参数,是这个对象在spring中的id值。在这个方法中通过这两个参数就获取到了这个参数,就可以在方法中对这个实例进行加工了。还要把这个加工好的对象交还给spring,通过参数把这个对象进行处理,交还给spring之后,执行我们配置好的初始化方法,然后将这个对象交给after这个方法,通过这个方法进行一次在加工,加工完毕之后,将这个参数传递个返回给spring。最后在客户处可以通过getBean方法进行获取。


        这就是bean引入了BeanPostProcessor这个技术之后的全部的过程分析。后置处理bean的运行原理分析。
        对于使用者,我们的作用就是让我们的bean实现这样的接口和接口中的方法,返回的值是Object


        具体过程:创建实例-注入-before方法-初始化方法-After方法
        有了这两个方法之后呢,实际的过程中,我们我们极少做初始化操作,所以,我们区分这个之前之后,这两个操作就合二为一的,

        实际上spring的初始操作使用的很少,所以,这个所谓的前后,也就没有什么前后之分了,两个挨着呢,实现其中的一个方法即可,也就是将代码写入到一个方法中就可以了。选谁,选After就可以了。但是啥也不干你也得有一个return  bean得到操作。需要注意的事before这个操作,我们必须return bean对象,这张图使我们必须要理解的内容。

package com.spring;

import com.spring.postBeanProcessor.Catagory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Auther: DaShu
 * @Date: 2021/6/24 21:17
 * @Description:
 */
public class TestPostBeanProcessor {
    @Test
    public void test1(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext1.xml");
        //-----------------------before-----------------------
        //PostBeanProcessorTest{id=10, name='xioajianren'}
        //-----------------------before-----------------------
        //------------------------init-----------------------
        //PostBeanProcessorTest{id=11, name='xiaojianren1'}
        //--------------------------init---------------------
        //---------------------------after-------------------------------
        //PostBeanProcessorTest{id=12, name='xiaojianren2'}
        //---------------------------after-------------------------------
    }
}


package com.spring.postBeanProcessor;

/**
 * @Auther: DaShu
 * @Date: 2021/6/24 21:38
 * @Description:
 */
public class Catagory {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "PostBeanProcessorTest{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public void init(){
        System.out.println("------------------------init-----------------------");
        System.out.println(this.toString());
        System.out.println("--------------------------init---------------------");
    }

}

package com.spring.postBeanProcessor;

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

/**
 * @Auther: DaShu
 * @Date: 2021/6/24 21:04
 * @Description:
 */
public class PostBeanProcessorTest implements BeanPostProcessor {


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof com.spring.postBeanProcessor.Catagory){
            System.out.println("-----------------------before-----------------------");
            System.out.println(bean.toString());
            ((com.spring.postBeanProcessor.Catagory)bean).setId(11);
            ((com.spring.postBeanProcessor.Catagory)bean).setName("xiaojianren1");
            System.out.println("-----------------------before-----------------------");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("---------------------------after-------------------------------");
        ((com.spring.postBeanProcessor.Catagory)bean).setId(12);
        ((com.spring.postBeanProcessor.Catagory)bean).setName("xiaojianren2");
        System.out.println(bean.toString());
        System.out.println("---------------------------after-------------------------------");
        return bean;
    }
}
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id = "catagory" class = "com.spring.postBeanProcessor.Catagory" init-method="init">
        <property name="id" value="10"/>
        <property name="name" value="xioajianren"/>
    </bean>
    <bean id = "postBeanProcessorTest" class = "com.spring.postBeanProcessor.PostBeanProcessorTest" />

</beans>

2:BeanPostProcessor对于AOP作用

        Spring工厂如何加工创建代理对象

        为什么通过原始对象id获取的是代理对象的id值呢?这是aop的核心原理的第二个问题。        

        Spring的工厂是如何加工和创建这个对象呢?
        在spring创建一个对象的时候,spring的工厂可以通过BeanPostProcessor这个工厂来进一步加工这个对象,我们的当时写的案例非常的简单,创建好对象之后,spring工厂调用,在后置BeanPostProcessor当中对这个bean进行赋值,然后将处理后的bean进行返回,当动态代理结合上beanpostprocessor之后,就可以实现这个通过原始的id返回对应的代理对象,其原理呢就是将这个加工代理对象的方法写入到这个后置处理bean中BeanPostProcessor当中的PostProcessorAfterInization这个方法中,然后将代理对象的地址进行返回即可。
我们知道我们很少做这个初始化操作,所以,这个前置处理和后置处理的位置是挨着的,他们的作用是完全一样的,这样的before我们就不用了,直接将bean对象进行返回,交还给spring即可,然后呢,这个所有加工的代理都写在了后置处理的这个方法中,调用的事Proxy.newProxyInstance()这个方法,这里的实现前边都讲过了,然后将创建好的代理对象交还给spring工厂,这样spring工厂就可以通过id获取的事代理对象,这就是通过原始对象的id值获取的事代理对象的加工。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TCP连接为什么是三次握手,而不是两次和四次

答案 阻止重复的历史连接同步初始序列号避免资源浪费 原因 阻止重复的历史连接&#xff08;首要原因&#xff09; 考虑这样一种情况&#xff1a; 客户端现在要给服务端建立连接&#xff0c;向服务端发送了一个SYN报文段&#xff08;第一次握手&#xff09;&#xff0c;以表示请…

Mininet学习记录(常用命令+创建网络拓扑+OpenDaylight显示拓扑结构)

目录 1.Mininet简介2.Mininet常用命令2.1创建网络拓扑常用参数2.2常用的内部交换命令 3.创建网络拓扑的三种方式3.1通过命令行创建3.2通过miniedit可视化界面创建3.3通过python脚本创建 4.问题总结 1.Mininet简介 Mininet 是由一些虚拟的终端节点 (end-hosts) 、交换机、路由器…

【STM32】TIM定时器

第一部分&#xff1a;定时器基本定时的功能&#xff1b; 第二部分&#xff1a;定时器的输出比较功能&#xff1b; 第三部分&#xff1a;定时器输入捕获的功能&#xff1b; 第四部分&#xff1a;定时器的编码接口。 1 TIM简介 TIM&#xff08;Timer&#xff09;定时器&#…

【数据库】数据库基于封锁机制的调度器,使冲突可串行化,保障事务和调度一致性

封锁使可串行化 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定期更…

《地理信息系统原理》笔记/期末复习资料(8. 数字高程模型)

目录 8. 数字高程模型 8.1 概述 8.1.1 数字高程模型概念 8.1.2 数字高程模型特点 8.2 DEM数据分布特征 8.2.1 格网状数据 8.2.2 离散数据 8.3 DEM的表示方法 8.3.1 数学方法 8.3.2 图形方法 8.3.3 DEM三维表达方法 8.4 TIN的生成方法 8.4.1 人工方法 8.4.2 程序自…

Android drawable layer-list右上角红点,xml布局实现,Kotlin

Android drawable layer-list右上角红点&#xff0c;xml布局实现&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android"http://schemas.android.com/apk/res/android"><itemandroid:id"id…

Vue3获取阴历/农历日期

安装插件 pnpm add chinese-lunar-calendar引入阳历/阴历切换函数 import {getLunar} from chinese-lunar-calendarexport function lunarDate(pDate){const year pDate.getFullYear()const month pDate.getMonth() 1const day pDate.getDate()const result getLunar(yea…

VMware安装Debian12.2作为服务器(无桌面)

[TOC]VMware安装Debian12.2作为服务器&#xff08;无桌面&#xff09; 下载Debian系统 官方网站&#xff1a;https://www.debian.org/index.zh-cn.html 创建新的虚拟机 打开VMware Workstation&#xff0c;点击创建新的虚拟机 向导虚拟机类型选择 一般我会选择典型&…

记录华为云服务器(Linux 可视化 宝塔面板)-- 防火墙篇

文章目录 前言安装防火墙防火墙设置防火墙操作1.设置开机启动防火墙2.查看防火墙开放哪些端口3.重载防火墙配置&#xff08;修改配置后重新启动才生效&#xff09;4.查看防火墙状态5.开启防火墙6.关闭防火墙 若遇到无法开启查询已开放的端口查询端口是否开放&#xff08;80&…

6-70.复数的加减运算(运算符重载)

###复数加减&#xff08;运算符重载&#xff09; 声明一个复数类CComplex&#xff08;类私有数据成员为double型的real和image&#xff09; 定义构造函数&#xff0c;用于指定复数的实部与虚部。 重载<<运算符&#xff0c;以格式realimage i的格式输出当前对象&#xf…

Eaxyx 让圆球跟随鼠标移动

如果出现2023&#xff0c;代表配置成功: 进入Eaxy官方网站&#xff0c;点击文档&#xff1a; 选择 函数->绘图函数->initgraph: 可以看见initgraph&#xff08;&#xff09;函数有如下三个参数: 现在我们想生成一个1280*720大小的窗口&#xff1a; 我们需写如下代码: 但…

2_企业级Nginx使用-day1

#企业级Nginx使用-day1 学习目标和内容 1、能够了解Nginx的信号参数 2、能够进行平滑升级Nginx 3、能够配置server虚拟机 4、能够部署上线项目到LNMP架构中 5、能够了解Nginx的常用官方模块 6、能够了解日志相关使用 一、重装和升级 在实际业务场景中&#xff0c;需要使用软件…

基于景区智慧灯杆、智能指路牌基础设施的景区建设应用

智慧景区是指运用现代信息技术手段&#xff0c;将景区内的资源、服务、管理等进行数字化、网络化和智能化整合&#xff0c;打造出高效便捷、安全舒适、互动体验和可持续发展的景区。智慧景区可以从以下几个方面进行体现&#xff1a; 智慧导览&#xff1a;通过使用智能化的导览…

高级前端面试中的三个 “送命题” !!!

原型与原型链 说到原型&#xff0c;就不得不提一下构造函数&#xff0c;首先我们看下面一个简单的例子&#xff1a; function Dog(name,age){this.name name;this.age age; }let dog1 new Dog("哈士奇",3); let dog2 new Dog("泰迪",2);首先创造空的…

Android HCI日志分析案例2

案例1--蓝牙音箱电量用完后&#xff0c;配对一直失败&#xff0c;提示PIN码不正确 基于MTK平台&#xff0c;通过MTKLogger开启保存HCI日志 问题定位分析 Android日志查看logcat 搜索到关键log 01-20 10:07:55.403760 978 1075 V bt_stack: [VERBOSE2:btm_inq.cc(2032)] …

二维粒子群算法航线规划

GitHub - gabrielegilardi/PathPlanning: Implementation of particle swarm optimization (PSO) for path planning when the environment is known.

GPC-SCP03安全通道协议

概述&#xff1a; 规范全称&#xff1a; GlobalPlatform Technology Secure Channel Protocol 03 Card Specification V2.3 - Amendment D Version 1.1.2 安全通道的建立的标志即通讯双方都形成三个安全通道共享密钥(Derived Session Key)&#xff0c;它们是Kmac, Krmac, Kenc…

Feign代替RestTemplate发起http请求

RestTemplate代码: // public Order queryOrderById(Long orderId) {// // 1.查询订单// Order order orderMapper.findById(orderId);// //String url "http://localhost:8081/user/" order.getUserId();// String url "htt…

Redis hash表源码解析

整体数据结构&#xff1a;链式hash解决hash冲突、采用渐进式hash来完成扩容过程。 /** 哈希表节点*/ typedef struct dictEntry {// 键void *key;// 值union {void *val;uint64_t u64;int64_t s64;} v;// 指向下个哈希表节点&#xff0c;形成链表struct dictEntry *next;} dict…

生成带依赖Jar 包的两种常用方式:IDEA打包工具:Artifacts 和 maven-shade-plugin

文章目录 前言1、IDEA打包工具&#xff1a;Artifacts1.1 创建Artifacts1.2 选择第三方jar文件1.3 打包Artifacts1.4 测试jar包 2、maven-shade-plugin2.1、pom文件添加2.2、打包2.3、测试jar包 总结 前言 当我们编写完Java程序后&#xff0c;为了提高执行效率通常会将应用程序…