本文主要是介绍Spring 源码梳理(二) BeanPostProcessor,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
BeanPostProcessor
1.BeanPostProcessor的概念
BeanPostProcessor是一个接口,它可以使得继承它的类成为一个"回调类"(自己起的称呼),继承的方法成为回调函数;它就像Windows中Hook Api ,就是一个钩子函数,先注册这个函数,且指定一个事件目标;那么当一个事件在执行前或者后时,就会触发这个函数的执行,可以在这个事件的前后做一些操作,影响这个事件。BeanPostProcessor就是这样的作用,它可以在类的初始化前后改变这个类的属性,从而影响实体类。
2.下面实际操作这个接口(接着上一篇已定义好的类)
1)调试准备
改变App类,改变后如下:
package com.mycompany.app;public class App
{private String says="App";public String getSays() {return says;}public void setSays(String says) {this.says = says;}public void say(){System.out.println("App.app():"+says);}
}
新增BeanPostProcessorApp类:
package com.mycompany.app;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class BeanPostProcessorApp implements BeanPostProcessor{public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {if(bean instanceof App){((App)bean).setSays("BeanPostProcessorApp");}return bean;}public Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {return bean;}}
Spring配置文件中增加:
<bean id="beanPostProcessorApp" class="com.mycompany.app.BeanPostProcessorApp"></bean>
新增BeanPostProcessorApp的测试类:
package com.mycompany.app;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanPostProcessorAppTest {public static void main(String[] args) {@SuppressWarnings("resource")ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringBean.xml"); App app = (App)applicationContext.getBean("app"); app.say();}}
2)调试如下:
首先进入refresh函数,上一篇已经提到了,这篇主要涉及refresh中的下面两个方法,registerBeanPostProcessors用来注册这个Hook函数,finishBeanFactoryInitialization是对配置文件中非延迟加载的bean进行实例化,如下图:
A:先分析registerBeanPostProcessors这个函数,我们调式进去看一下,首先会进入org.springframework.context.support中的
PostProcessorRegistrationDelegate类,然后到了registerBeanPostProcessors方法,如下图:
这个方法会把刚才的BeanPostProcessorApp注册到beanFactory中,然后我们就会在beanFactory中看到beanPostProcessors多了一个我们自己的BeanPostProcessorApp,下图所示:
到此,这个钩子已经注册完成,当对类进行实例化的时候就会调用该钩子函数;
B:然后分析finishBeanFactoryInitialization函数,它主要是对bean进行初始化,调用顺序如下:
(1).org.springframework.context.support.AbstractApplicationContext中的
(2).org.springframework.beans.factory.support.DefaultListableBeanFactory中的
(3).org.springframework.beans.factory.support.AbstractBeanFactory中的
(4).org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory中的
(5).org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory中的
(6).org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory中的
(7).先进入applyBeanPostProcessorsBeforeInitialization:
由于beanPostProcessor有多个(之前已经看到了,除了我们自己的“BeanPostProcessorApp”,还有几个暂不知其意,以后遇到再进行分析), 所以会找这些processors的postProcessBeforeInitialization方法实现, 当for循环到我们的processor时,就会执行
我们自己写的方法:
自己的方法:
到此就完成了我们的目的,对App这个类,进行Hook,而且已经改变了实体类App的says的值。最后当我们进行getBean("app")的操作时,我们进行打印结果如下:
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:Arial Black;">App.app():BeanPostProcessorApp</span></span>
同样的,After的操作同Before一样;
注:
上面的bean的初始化,是在读取配置文件的时候进行的; 如果是延迟加载的情况,是否能够Hook成功呢。 对于App和BeanPostProcessorApp同时延迟加载或者任意一个延迟加载的情况,先思考,后面再进行分析。
转载地址:https://blog.csdn.net/Jintao_Ma/article/details/52329090
这篇关于Spring 源码梳理(二) BeanPostProcessor的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!