- BeanPostProcessor介绍
- BeanPostProcessor执行流程
- BeanPostProcessor使用
- Book
- BookProxyBeanPostProcessor
- main
- 全量代码
- 执行结果
- 源码解析
- 总结
BeanPostProcessor
接口使得程序可以在Bean被初始化的前后执行自定义动作,如检查或更改Bean
的属性值、包装即将注册到BeanFactory
的singletonObjects
中的原对象等。
BeanPostProcessor
接口提供了如下方法:
方法 | 描述 |
---|---|
Object postProcessBeforeInitialization(Object bean, String beanName) | 在容器调用Bean 的InitializingBean#afterPropertiesSet() 或自定义的init-method 之前,调用该方法进行处理;传入的bean对象属性此时已经装配好。 |
Object postProcessAfterInitialization(Object bean, String beanName) | 在容器调用Bean 的InitializingBean#afterPropertiesSet() 或自定义的init-method 之后,调用该方法进行处理;传入的bean对象属性此时已经装配好。 |
BeanPostProcessor
的执行会在Bean
实例化并装配好属性之后,before和after之间会插入Bean
的AfterPropertiesSet()
和init-method
的执行。
下图能比较好的反应出过程:
BeanPostProcessor使用
接下来写个例子。全量代码会在最后贴出来,直接CV运行即可。
BookBook
类,它实现了InitializingBean
接口,其afterPropertiesSet()
方法仅输出一行信息用来记录执行流程;还有一个customInit()
方法使其加入到Spring
的init-method
的执行过程;该类还有一个show()
方法,用来在后面的BeanPostProcessor
处理器中对原始的Book
对象生成一个代理类,该代理类将对show()
方法进行增强处理,用来让咱们的BeanPostProcessor
能实际干点事儿。
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("%-70s:%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("%-70s:%s{%s}%n", "------Book#afterPropertiesSet", this.getClass().getSimpleName(), this);
}
}
BookProxyBeanPostProcessor
BookProxyBeanPostProcessor
实现了BeanPostProcessor
接口;在其postProcessBeforeInitialization()
方法中对Book
类型进行判断,如果是Book
类型则使用CGLIB生成其代理,用来增强Book#show()
方法,在其前后各打印一句话。
public class BookProxyBeanPostProcessor implements BeanPostProcessor {
/**
* 在容器调用Bean的InitializingBean#afterPropertiesSet()或自定义的init-method之前,调用该方法进行处理;传入的bean对象属性此时已经装配好。
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-70s:%s{%s}%n",
"------BookProxyBeanPostProcessor#postProcessBeforeInitialization",
bean.getClass().getSimpleName(),
bean);
if (Book.class.equals(bean.getClass())) {
System.out.printf("3[1;33m%-70s:对[%s]的3[1;31mshow()3[1;33m方法进行增强 3[0m%n",
"------BookProxyBeanPostProcessor#postProcessBeforeInitialization",
bean.getClass().getSimpleName());
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Book.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, methodProxy) -> {
if (!method.equals(Book.class.getMethod("show"))) {
return methodProxy.invokeSuper(obj, args);
}
System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行前");
Object result = methodProxy.invokeSuper(obj, args);
System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行后");
return result;
});
Book book = (Book) enhancer.create();
book.setName(((Book) bean).getName());
book.setAuthor(((Book) bean).getAuthor());
return book;
}
return bean;
}
/**
* 在容器调用Bean的InitializingBean#afterPropertiesSet()或自定义的init-method之后,调用该方法进行处理;传入的bean对象属性此时已经装配好。
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-70s:%s{%s}%n",
"------BookProxyBeanPostProcessor#postProcessAfterInitialization",
bean.getClass().getSimpleName(), bean);
return bean;
}
}
main
定义一个Book
类型的GenericBeanDefinition
,将Book#customInit()
添加到BeanDefinition
中,并设置MutablePropertyValues
用于初始化后的属性装配。
同时将BookProxyBeanPostProcessor
注册到容器中。
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
GenericBeanDefinition bookBeanDefinition = new GenericBeanDefinition();
bookBeanDefinition.setBeanClass(Book.class);
bookBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
//设置属性
bookBeanDefinition.setPropertyValues(new MutablePropertyValues()
.addPropertyValue(new PropertyValue("name", "《非暴力沟通》"))
.addPropertyValue(new PropertyValue("author", "马歇尔·卢森堡"))
);
bookBeanDefinition.setInitMethodName("customInit");//设置初始化方法
context.registerBeanDefinition("book", bookBeanDefinition);//注册BeanDefinition
context.registerBean("bookProxyBeanPostProcessor", BookProxyBeanPostProcessor.class);//注册Bean后处理器
context.refresh();//刷新容器
context.getBean("book", Book.class).show();
}
全量代码
package com.baiyang.beanpostprocessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
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;
public class BookProxyBeanPostProcessor implements BeanPostProcessor {
/**
* 在容器调用Bean的InitializingBean#afterPropertiesSet()或自定义的init-method之前,调用该方法进行处理;传入的bean对象属性此时已经装配好。
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-70s:%s{%s}%n",
"------BookProxyBeanPostProcessor#postProcessBeforeInitialization",
bean.getClass().getSimpleName(),
bean);
if (Book.class.equals(bean.getClass())) {
System.out.printf("3[1;33m%-70s:对[%s]的3[1;31mshow()3[1;33m方法进行增强 3[0m%n",
"------BookProxyBeanPostProcessor#postProcessBeforeInitialization",
bean.getClass().getSimpleName());
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Book.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, methodProxy) -> {
if (!method.equals(Book.class.getMethod("show"))) {
return methodProxy.invokeSuper(obj, args);
}
System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行前");
Object result = methodProxy.invokeSuper(obj, args);
System.out.printf("3[1;33m%-70s3[0m%n", "Book#show()执行后");
return result;
});
Book book = (Book) enhancer.create();
book.setName(((Book) bean).getName());
book.setAuthor(((Book) bean).getAuthor());
return book;
}
return bean;
}
/**
* 在容器调用Bean的InitializingBean#afterPropertiesSet()或自定义的init-method之后,调用该方法进行处理;传入的bean对象属性此时已经装配好。
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.printf("%-70s:%s{%s}%n",
"------BookProxyBeanPostProcessor#postProcessAfterInitialization",
bean.getClass().getSimpleName(), bean);
return bean;
}
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
GenericBeanDefinition bookBeanDefinition = new GenericBeanDefinition();
bookBeanDefinition.setBeanClass(Book.class);
bookBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);//指定为单例模式
//设置属性
bookBeanDefinition.setPropertyValues(new MutablePropertyValues()
.addPropertyValue(new PropertyValue("name", "《非暴力沟通》"))
.addPropertyValue(new PropertyValue("author", "马歇尔·卢森堡"))
);
bookBeanDefinition.setInitMethodName("customInit");//设置初始化方法
context.registerBeanDefinition("book", bookBeanDefinition);//注册BeanDefinition
context.registerBean("bookProxyBeanPostProcessor", BookProxyBeanPostProcessor.class);//注册Bean后处理器
context.refresh();//刷新容器
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("%-70s:%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("%-70s:%s{%s}%n", "------Book#afterPropertiesSet", this.getClass().getSimpleName(), this);
}
}
}
执行结果
从执行结果即可反应出BeanPostProcessor
的执行流程。
spring版本:5.2.9
该节源码解析仅仅只讲关键的与BeanPostProcessor
相关的位置。如果想要知其与BeanPostProcessor
前后的细节,可以针对本节的所讲述的位置自行Debug进入详细阅读。
首先是Spring容器的经典入口:refresh()
然后调用AbstractApplicationContext
所持有的实际BeanFactory
(DefaultListableBeanFactory
)句柄的preInstantiateSingletons()
做Bean容器的初始化工作。
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
:
进入getBean()
方法,由于我们是新创建bean,所以流程将会是getBean()->doGetBean()->createBean()->doCreateBean()
的流程,咱们一路DEBUG到doCreateBean()
:
由于我们重点是在了解BeanPostProcessor
的内部执行流程上,所以上图隐藏了一些不太相关的代码,避免干扰;
此时还没有调用到BeanPostProcessor
,所以从doCreateBean
的执行流程可以看出,此时已经将Bean进行的实例化,并且装配好了属性值。
接着进入到关键方法exposedObject = initializeBean(beanName, exposedObject, mbd);
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
从上面的方法可以看出BeanPostProcessor#postProcessBeforeInitialization
是可以改变即将注册到BeanFactory
中的实际对象的。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
从上面的invokeInitMethods()
可以看到包含了InitializingBean
接口的处理与init-method
的方法处理流程;
init-method
方法最终会通过反射执行。
最后就是BeanPostProcessor#postProcessAfterInitialization()
方法的执行:
至此initializeBean()
方法执行结束返回到doCreateBean()
:
doCreateBean()
将initializeBean()
返回的对象返回出去,一路回到getSingleton()
:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory>)
可以看到此时,已经将一个经过了BeanPostProcess
处理的Bean
对象注册到了BeanFactory
中(在本例子里面是我们的BookProxyBeanPostProcessor
创建的Book
对象的代理类)。
以上通过围绕BeanPostProcessor
创建一个对指定Bean
对象的代理对象,对其特定方法进行代理增强的例子,来介绍了BeanPostProcessor
的应用。
同时,通过对源码的浅析来对BeanPostProcessor
的执行前后流程进行了讲解。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)