<div class="operating">
<a class="href-article-edit slide-toggle">版权</a>
</div>
</div>
</div>
</div>
<div id="blogHuaweiyunAdvert"></div>
<div id="blogColumnPayAdvert">
<div class="column-group">
<div class="column-group-item column-group0 column-group-item-one">
<div class="item-l">
<a class="item-target" href="https://blog.csdn.net/u013632755/category_3193091.html" target="_blank" title="Spring" data-report-click="{"spm":"1001.2101.3001.6332"}">
<img class="item-target" src="/i/ll/?i=2021010218004631.jpg?x-oss-process=image/resize,m_fixed,h_224,w_224" alt="">
<span class="title item-target">
<span>
<span class="tit">Spring</span>
<span class="dec">专栏收录该内容</span>
</span>
</span>
</a>
</div>
<div class="item-m">
<span>12 篇文章</span>
<span>0 订阅</span>
</div>
<div class="item-r">
<a class="item-target article-column-bt articleColumnFreeBt" data-id="3193091">订阅专栏</a>
</div>
</div>
</div>
</div>
<article class="baidu_pl">
<div id="article_content" class="article_content clearfix">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-25cebea3f9.css">
<div id="content_views" class="markdown_views prism-atom-one-light">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<p></p>
文章目录
- InstantiationAwareBeanPostProcessor介绍
- InstantiationAwareBeanPostProcessor执行流程
- InstantiationAwareBeanPostProcessor使用
- Book
- Pen
- BookProxyInstantiationAwareBeanPostProcessor
- main
- 全量代码
- 执行结果
- 源码解析
- 总结
InstantiationAwareBeanPostProcessor介绍
InstantiationAwareBeanPostProcessor
接口扩展了BeanPostProcessor
子接口,提供了Bean
被实例化之前、Bean
实例化之后、Bean
属性装配前更细粒度控制Bean
创建流程的处理。
由于InstantiationAwareBeanPostProcessor
扩展了BeanPostProcessor
接口,所以该篇文章部分内容会与BeanPostProcessor
接口的流程重合;尽管如此,也建议在看该篇文章前,先阅读关于BeanPostProcessor
接口的详细介绍与源码解析:Spring之Bean后处理器——BeanPostProcessor的使用与源码解析
InstantiationAwareBeanPostProcessor
接口比BeanPostProcessor
新增了如下方法:
方法 | 描述 |
| 在 |
| 在 |
| 在 |
InstantiationAwareBeanPostProcessor执行流程
InstantiationAwareBeanPostProcessor
流程如下:
- 执行
Bean
实例化之前,执行postProcessBeforeInstantiation()
; - 执行
Bean
实例化之后执行postProcessAfterInstantiation()
; - 执行
Bean
属性装配前执行postProcessProperties()
; - 在
Bean
属性装配后执行postProcessBeforeInitialization()
; - 在
Bean
的Init相关初始化完毕后执行postProcessAfterInitialization()
;
下图能比较好的反应出过程:
InstantiationAwareBeanPostProcessor使用
接下来写个例子。全量代码会在最后贴出来,直接CV运行即可。
Book
Book
类,它实现了InitializingBean
接口,其afterPropertiesSet()
方法仅输出一行信息用来记录执行流程;还有一个customInit()
方法使其加入到Spring
的init-method
的执行过程;该类还有一个show()
方法,用来在后面的BookProxyInstantiationAwareBeanPostProcessor
处理器中对原始的Book
对象生成一个代理类,该代理类将对show()
方法进行增强处理,用来让咱们的BeanPostProcessor
能实际干点事儿。
但是由于BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
返回了代理对象,所以后续Book
后续的初始化都不会在进行,所以其afterPropertiesSet()
与customInit()
方法也不会再调用。
public class Book implements InitializingBean {
private String name;
private String author;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public void show() {
System.out.printf("book#show():%s\n", this);
}
public void customInit() {
System.out.printf("%-85s:%s{%s}%n", "------Book#customInit", this.getClass().getSimpleName(), this);
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.printf("%-85s:%s{%s}%n", "------Book#afterPropertiesSet", this.getClass().getSimpleName(), this);
}
}
Pen
Pen
类与Book
类一样,它实现了InitializingBean
接口,其afterPropertiesSet()
方法仅输出一行信息用来记录执行流程;还有一个customInit()
方法使其加入到Spring
的init-method
的执行过程;
public class Pen implements InitializingBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pen{" +
"name='" + name + '\'' +
'}';
}
public void customInit() {
System.out.printf("%-85s:%s{%s}%n", "------Pen#customInit", this.getClass().getSimpleName(), this);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.printf("%-85s:%s{%s}%n", "------Pen#afterPropertiesSet", this.getClass().getSimpleName(), this);
}
}
BookProxyInstantiationAwareBeanPostProcessor
BookProxyInstantiationAwareBeanPostProcessor
实现了InstantiationAwareBeanPostProcessor
接口;在其postProcessBeforeInstantiation()
方法中对Book
类型进行判断,如果是Book
类型则使用CGLIB生成其代理,用来增强Book#show()
方法,在其前后各打印一句话。其余方法都仅输出一条信息,用来描述其执行过程。
public class BookProxyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.printf("%-85s:%s%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
//判断传入的beanClass是否是Book类型
if (Book.class.equals(beanClass)) {
System.out.printf("\033[1;33m%-85s:对[%s]的\033[1;31mshow()\033[1;33m方法进行增强 \033[0m%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
//创建Book类的代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Book.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, methodProxy) -> {
//如果不是show()方法则直接调用返回
if (!method.equals(Book.class.getMethod("show"))) {
return methodProxy.invokeSuper(obj, args);
}
//对show()做增强处理
System.out.printf("\033[1;33m%-70s\033[0m%n", "Book#show()执行前");
Object result = methodProxy.invokeSuper(obj, args);
System.out.printf("\033[1;33m%-70s\033[0m%n", "Book#show()执行后");
return result;
});
Book book = (Book) enhancer.create();
book.setName("《非暴力沟通》");
book.setAuthor("马歇尔·卢森堡");
return book;
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation", bean.getClass().getSimpleName(), bean);
return true;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInitialization", bean.getClass().getSimpleName(), bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInitialization", bean.getClass().getSimpleName(), bean);
return bean;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", "------BookProxyInstantiationAwareBeanPostProcessor#postProcessProperties", bean.getClass().getSimpleName(), bean);
pvs.forEach((name) -> {
System.out.printf("%85s:%s {%s=%s}%n", "pvs", bean.getClass().getSimpleName(), name.getName(), name.getValue());
});
return pvs;
}
}
main
定义一个Book
类型与Pen
类型的GenericBeanDefinition
,将Book
与Pen
的customInit()
添加到BeanDefinition
中,并设置Pen
的MutablePropertyValues
用于初始化后的属性装配。
同时将BookProxyInstantiationAwareBeanPostProcessor
注册到容器中。
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
//注册Book的BeanDefinition
GenericBeanDefinition bookBeanDefinition = new GenericBeanDefinition();
bookBeanDefinition.setBeanClass(Book.class);
bookBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
bookBeanDefinition.setInitMethodName("customInit");//设置初始化方法
context.registerBeanDefinition("book", bookBeanDefinition);
//注册Pen的BeanDefinition
GenericBeanDefinition penBeanDefinition = new GenericBeanDefinition();
penBeanDefinition.setBeanClass(Pen.class);
penBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
penBeanDefinition.setInitMethodName("customInit");//设置初始化方法
//设置pen属性
penBeanDefinition.setPropertyValues(new MutablePropertyValues()
.addPropertyValue(new PropertyValue("name", "英雄钢笔"))
);
context.registerBeanDefinition("pen", penBeanDefinition);//注册BeanDefinition
//注册BookProxyInstantiationAwareBeanPostProcessor后处理器
context.registerBean(BookProxyInstantiationAwareBeanPostProcessor.class);
//刷新容器
context.refresh();
//获取Book的bean对象,调用show()方法
context.getBean("book", Book.class).show();
}
全量代码
package com.baiyang.beanpostprocessor.instantiationaware;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.context.support.GenericApplicationContext;
import java.util.concurrent.atomic.AtomicInteger;
public class BookProxyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public static AtomicInteger COUNT = new AtomicInteger();
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.printf("%-85s:%s%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
//判断传入的beanClass是否是Book类型
if (Book.class.equals(beanClass)) {
System.out.printf("\033[1;33m%-85s:对[%s]的\033[1;31mshow()\033[1;33m方法进行增强 \033[0m%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation", beanClass.getSimpleName());
//创建Book类的代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Book.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, methodProxy) -> {
//如果不是show()方法则直接调用返回
if (!method.equals(Book.class.getMethod("show"))) {
return methodProxy.invokeSuper(obj, args);
}
//对show()做增强处理
System.out.printf("\033[1;33m%-70s\033[0m%n", "Book#show()执行前");
Object result = methodProxy.invokeSuper(obj, args);
System.out.printf("\033[1;33m%-70s\033[0m%n", "Book#show()执行后");
return result;
});
Book book = (Book) enhancer.create();
book.setName("《非暴力沟通》");
book.setAuthor("马歇尔·卢森堡");
return book;
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation", bean.getClass().getSimpleName(), bean);
return true;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInitialization", bean.getClass().getSimpleName(), bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessAfterInitialization", bean.getClass().getSimpleName(), bean);
return bean;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------BookProxyInstantiationAwareBeanPostProcessor#postProcessProperties", bean.getClass().getSimpleName(), bean);
pvs.forEach((name) -> {
System.out.printf("%85s:%s {%s=%s}%n", "pvs", bean.getClass().getSimpleName(), name.getName(), name.getValue());
});
return pvs;
}
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
//注册Book的BeanDefinition
GenericBeanDefinition bookBeanDefinition = new GenericBeanDefinition();
bookBeanDefinition.setBeanClass(Book.class);
bookBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
bookBeanDefinition.setInitMethodName("customInit");//设置初始化方法
context.registerBeanDefinition("book", bookBeanDefinition);
//注册Pen的BeanDefinition
GenericBeanDefinition penBeanDefinition = new GenericBeanDefinition();
penBeanDefinition.setBeanClass(Pen.class);
penBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
penBeanDefinition.setInitMethodName("customInit");//设置初始化方法
//设置pen属性
penBeanDefinition.setPropertyValues(new MutablePropertyValues()
.addPropertyValue(new PropertyValue("name", "英雄钢笔"))
);
context.registerBeanDefinition("pen", penBeanDefinition);//注册BeanDefinition
//注册BookProxyInstantiationAwareBeanPostProcessor后处理器
context.registerBean(BookProxyInstantiationAwareBeanPostProcessor.class);
//刷新容器
context.refresh();
//获取Book的bean对象,调用show()方法
context.getBean("book", Book.class).show();
}
static class Book implements InitializingBean {
private String name;
private String author;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public void show() {
System.out.printf("book#show():%s\n", this);
}
public void customInit() {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Book#customInit", this.getClass().getSimpleName(), this);
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Book#afterPropertiesSet", this.getClass().getSimpleName(), this);
}
}
static class Pen implements InitializingBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pen{" +
"name='" + name + '\'' +
'}';
}
public void customInit() {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Pen#customInit", this.getClass().getSimpleName(), this);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.printf("%-85s:%s{%s}%n", COUNT.addAndGet(1) + "------Pen#afterPropertiesSet", this.getClass().getSimpleName(), this);
}
}
}
执行结果
从执行结果即可反应出InstantiationAwareBeanPostProcessor
的执行流程:
1~3
行的结果是加载Book
的输出,由于BookProxyInstantiationAwareBeanPostProcessor
在执行postProcessBeforeInstantiation
方法之后返回了Book
的代理对象,所以后续对Book
的所有初始化将不再继续,调用了BeanDefinition#postProcessAfterInitialization
之后就直接返回注册了。
4~10
行的输出结果可以看出,Pen
类的加载,由于没有任何InstantiationAwareBeanPostProcessor
对其做任何处理,所以走完了所有的常规Bean
加载流程。
最后三行输出执行了从容器中获取的book
对象的show()
方法,可以看出我们通过BookProxyInstantiationAwareBeanPostProcessor
成功的改变了原本注入到容器中的Book
对象,并成功对其show()
方法进行了增强处理。
源码解析
spring版本:5.2.9
该节源码解析仅仅只讲关键的与InstantiationAwareBeanPostProcessor
相关的位置。如果想要知其与InstantiationAwareBeanPostProcessor
前后的细节,可以针对本节的所讲述的位置自行Debug进入详细阅读。
首先是Spring容器的经典入口:refresh()
然后调用AbstractApplicationContext
所持有的实际BeanFactory
(DefaultListableBeanFactory
)句柄的preInstantiateSingletons()
做Bean容器的初始化工作。
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
:
bean的创建流程:getBean()->doGetBean()->createBean()->doCreateBean()
我们直接定位到createBean()
从上面的流程可以看出,当执行了resolveBeforeInstantiation(beanName,mbdToUse)
方法后,有返回bean
对象,则直接return
出去了。 如果没有返回bean
对象,则会执行doCreateBean()
进行真正的常规创建流程。
在本文章的例子中,初始化book
对象的流程中BookProxyInstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation()
返回了book
的代理对象,所以在上面的流程中,直接返回出去了,没有执行doCreateBean()
方法。
接下进入resolveBeforeInstantiation(beanName,mbdToUse)
:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
createBean()
将对象返回出去,一路回到getSingleton()
:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
可以看到此时,已经将一个经过了InstantiationAwareBeanPostProcessor
处理的Bean
对象注册到了BeanFactory
中(在本例子里面是我们的BookProxyInstantiationAwareBeanPostProcessor
创建的Book
对象的代理类)。
经过以上流程可以看出,当InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
如果返回了对象的话,那么Bean
的创建流程将会直接结束返回该对象。
接下来讲InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
不返回对象的Bean
创建流程,在该例子里面是Pen
的创建流程:
上面的流程中,由于执行了BookProxyInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
没有返回对象,所以会执行后面的doCreateBean()
来创建对象。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
在上面的流程中,先通过反射创建了对象,然后调用populateBean()
进行属性装配,属性装配后,执行Bean的初始化流程,包含了BeanPostProcessor
的前后置处理、init-method
相关处理。
我们知道,在InstantiationAwareBeanPostProcessor
中目前还只执行了postProcessBeforeInstantiation()
,还有剩下postProcessAfterInstantiation()
、postProcessProperties()
、postProcessBeforeInitialization()
、postProcessAfterInitialization()
没有执行。
我们先看populateBean()
中的逻辑:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
从上面的流程可以看出,populateBean()
的流程是先调用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()
,然后调用其InstantiationAwareBeanPostProcessor#postProcessPropertyValues()
,最后进行属性的装配工作。
此时和我们前面描述的执行流程保持一致。
接下来是postProcessBeforeInitialization()
、postProcessAfterInitialization()
的执行还没有做。
返回到上层
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
:
从上面的initializeBean()
的流程可以看到我们首先调用了BeanPostProcessor#postProcessBeforeInitialization()
,然后执行了invokeInitMethods()
来处理bean的实现的InitializingBean
接口的afterPropertiesSet()
与自定义init-method
;最后执行BeanPostProcessor#postProcessAfterInitialization()
;
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
从上面的invokeInitMethods()
可以看到包含了InitializingBean
接口的处理与init-method
的方法处理流程;
init-method
方法最终会通过反射执行。最后就是BeanPostProcessor#postProcessAfterInitialization()
方法的执行:
至此,所有的InstantiationAwareBeanPostProcessor
接口涉及到的流程都执行完毕,与前面讲述的流程一样,最后就是返回到getSingleton()
将最后最终的对象注册到容器中。
总结
以上通过围绕InstantiationAwareBeanPostProcessor
创建一个对指定Bean
对象的代理对象,对其特定方法进行代理增强的例子,来介绍了InstantiationAwareBeanPostProcessor
的应用,以及描述了InstantiationAwareBeanPostProcessor
的"短路"会控制到后续常规Bean
的创建流程。
同时,通过对源码的浅析来对InstantiationAwareBeanPostProcessor
的执行前后流程进行了讲解。
https://blog.csdn.net/u013632755/article/details/124596220
标签:String,Spring,bean,public,Bean,Book,源码,InstantiationAwareBeanPostProcessor,name From: https://blog.51cto.com/u_12948550/6575903