😉😉 学习交流群:
✅✅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 {@Testpublic 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;}@Overridepublic 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 {@Overridepublic 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;}@Overridepublic 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值获取的事代理对象的加工。