spring4.1.8 扩展实战之七:控制 bean(BeanPostProcessor 接口)
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码): http://github.com/zq2599/blog_demos
-
本章是《spring4.1.8 扩展实战》的第七篇,我们来尝试在容器初始化的时候对 bean 实例做设置;
控制 bean 的两种扩展方式
-
两种方式可以对 bean 做控制(例如修改某个成员变量)
-
改变 bean 的定义(BeanFactoryPostProcessor 接口) ,可以想象成修改了 class 文件,这样实例化出来的每个对象都变了;
-
只改变实例化的对象(BeanPostProcessor 接口);
-
上述两种方式都能控制 bean,第一种请参照 《spring4.1.8扩展实战之五:改变bean的定义(BeanFactoryPostProcessor接口)》 ,今天我们来研究第二种:改变实例化的对象;
本章概览
-
全文由以下部分组成:
-
spring 源码分析,了解 BeanPostProcessor 接口的实现类如何被注册到 spring 容器;
-
spring 源码分析,了解已经注册到 spring 环境的 BeanPostProcessor 实现类如何被使用;
-
实战,开发一个 BeanPostProcessor 实现类,验证是否能用来改变指定的 bean;
源码分析:BeanPostProcessor 接口的实现类如何被注册到 spring 容器
-
从 spring 容器的初始化代码看起吧,看 AbstractApplicationContext 类的 refresh 方法,如下图所示,红框中的方法负责将 BeanPostProcessor 接口的实现类注册到 spring 容器:
-
展开 registerBeanPostProcessors 方法,发现是委托 PostProcessorRegistrationDelegate 类的静态方法 registerBeanPostProcessors 来完成注册工作的:
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
复制代码
-
展开 PostProcessorRegistrationDelegate.registerBeanPostProcessors 方法,里面的代码逻辑简洁整齐,意图目的一目了然:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取所有实现BeanPostProcessor接口的bean的名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
//注意,此时尽管注册操作还没有开始,但是之前已经有一些特殊的bean已经注册进来了,
//详情请看AbstractApplicationContext类的prepareBeanFactory方法,
//因此getBeanPostProcessorCount()方法返回的数量并不为零,
//加一是因为方法末尾会注册一个ApplicationListenerDetector接口的实现类
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
//这里的BeanPostProcessorChecker也是个BeanPostProcessor的实现类,用于每个bean的初始化完成后,做一些简单的检查
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
//如果这些bean还实现了PriorityOrdered接口(在意执行顺序),就全部放入集合priorityOrderedPostProcessors
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
//集合internalPostProcessors,用来存放同时实现了PriorityOrdered和MergedBeanDefinitionPostProcessor接口的bean
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
//集合orderedPostProcessorNames用来存放实现了Ordered接口的bean的名称(在意执行顺序)
List<String> orderedPostProcessorNames = new ArrayList<String>();
//集合nonOrderedPostProcessorNames用来存放即没实现PriorityOrdered接口,也没有实现Ordered接口的bean的名称(不关心执行顺序)
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
//实现了PriorityOrdered接口的bean,都放入集合priorityOrderedPostProcessors
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
//实现了MergedBeanDefinitionPostProcessor接口的bean,都放入internalPostProcessors集合
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
//实现了Ordered接口的bean,将其名称都放入orderedPostProcessorNames集合
orderedPostProcessorNames.add(ppName);
}
else {
//既没实现PriorityOrdered接口,也没有实现Ordered接口的bean,将其名称放入nonOrderedPostProcessorNames集合
nonOrderedPostProcessorNames.add(ppName);
}
}
//实现了PriorityOrdered接口的bean排序
OrderComparator.sort(priorityOrderedPostProcessors);
//注册到容器
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
//处理所有实现了Ordered接口的bean
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
//前面将所有实现了PriorityOrdered和MergedBeanDefinitionPostProcessor的bean放入internalPostProcessors,
//此处将所有实现了Ordered和MergedBeanDefinitionPostProcessor的bean放入internalPostProcessors
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//实现了Ordered接口的bean排序
OrderComparator.sort(orderedPostProcessors);
//注册到容器
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
//此处将其余实现了MergedBeanDefinitionPostProcessor的bean放入internalPostProcessors
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//注册到容器
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
OrderComparator.sort(internalPostProcessors);
//将所有实现了MergedBeanDefinitionPostProcessor接口的bean也注册到容器
registerBeanPostProcessors(beanFactory, internalPostProcessors);
//创建一个ApplicationListenerDetector对象并且注册到容器,这就是前面计算beanProcessorTargetCount的值时加一的原因
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
复制代码
-
以上代码已加注释,就不多解读了,有一点需要注意:对于实现了 MergedBeanDefinitionPostProcessor 接口的 bean,在前面几次调用 registerBeanPostProcessors 方法的时候已经注册过了,那么在最后执行的==registerBeanPostProcessors(beanFactory, internalPostProcessors)==,岂不是将一个 bean 注册了多次?
-
为了弄清楚这个问题需要看 registerBeanPostProcessors 方法:
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
//对每个bean都调用beanFactory.addBeanPostProcessor方法来注册
beanFactory.addBeanPostProcessor(postProcessor);
}
}
复制代码
-
addBeanPostProcessor 方法的代码在 AbstractApplicationContext 类中,如下所示,==先删除再添加,这样反复注册也没有问题==:
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
//如果已经注册,就先删除掉
this.beanPostProcessors.remove(beanPostProcessor);
//再注册
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
}
复制代码
-
至此,我们已经弄清楚了 BeanPostProcessor 实现类的 bean 注册到 spring 容器的逻辑,接下来看看 spring 容器如何使用这些 bean;
源码分析,BeanPostProcessor 实现类如何被使用
-
要弄清楚 BeanPostProcessor 接口的实现类是在哪里被用到的,还是从负责容器初始化的 AbstractApplicationContext 类的 refresh 方法看起,如下图红框中的 finishBeanFactoryInitialization 方法,就是负责实例化和初始化 bean 的:
-
从 finishBeanFactoryInitialization 方法到 BeanPostProcessor 的实现类被使用,中间有多层逻辑和调用,篇幅所限就不逐个展开了,直接列出堆栈信息,您可以根据此信息去查看对应源码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean()
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject()
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton()
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean()
org.springframework.beans.factory.support.AbstractBeanFactory.getBean()
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons()
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization()
org.springframework.context.support.AbstractApplicationContext.refresh()
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh()
org.springframework.boot.SpringApplication.refresh()
org.springframework.boot.SpringApplication.refreshContext()
org.springframework.boot.SpringApplication.run()
org.springframework.boot.SpringApplication.run()
org.springframework.boot.SpringApplication.run()
复制代码
-
根据上述堆栈信息,直接查看 AbstractAutowireCapableBeanFactory 类的 initializeBean()方法:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//对已经实例化的bean,在初始化前用BeanPostProcessor实现类去处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//bean的初始化
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//对已经实例化的bean,在初始化后用BeanPostProcessor实现类去处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
复制代码
-
如上所示,我们最关注的代码是==applyBeanPostProcessorsBeforeInitialization==和==applyBeanPostProcessorsAfterInitialization==这两个方法,它们分别在 bean 的初始化方法==invokeInitMethods==的前后被执行;
-
先看看 applyBeanPostProcessorsBeforeInitialization 方法,逻辑非常简单,就是取出所有已注册的 BeanPostProcessor 实现类,执行其 postProcessBeforeInitialization 方法,入参是当前正在做实例化和初始化的 bean 实例:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//逐一执行每个BeanPostProcessor实现类的postProcessBeforeInitialization方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
复制代码
-
在 invokeInitMethods 方法执行完毕后会执行 applyBeanPostProcessorsAfterInitialization 方法,代码如下,与 applyBeanPostProcessorsBeforeInitialization 如出一辙,仅有的不同是调用的 beanProcessor 的方法变成了 postProcessAfterInitialization:
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//逐一执行每个BeanPostProcessor实现类的postProcessAfterInitialization方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
复制代码
-
以上就是 spring 容器初始化过程中对 BeanPostProcessor 实现类的使用场景,此时还剩一点疑问需要澄清:==在分析注册过程的时候,曾看到实现 MergedBeanDefinitionPostProcessor 接口的 bean 是最后注册的,那么这些 MergedBeanDefinitionPostProcessor 实现类在 spring 容器中是何处使用的呢?==
-
为了搞清这个问题,来看看 AbstractAutowireCapableBeanFactory 类的 doCreateBean 方法,前面我们分析的 initializeBean 方法就是在这里面被调用的:
-
如上图所示,红框中就是用所有 MergedBeanDefinitionPostProcessor 实现类去处理当前正在实例化的 bean,然后才会执行绿框中的 initializeBean 方法(里面是我们刚才分析的 bean 的初始化,BeanPostProcessor 实现类被使用的逻辑);
-
来看看红框中的 applyMergedBeanDefinitionPostProcessors 方法,主要目的是处理特殊的合成 bean 的定义类:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
throws BeansException {
try {
//取出每个注册的BeanPostProcessor实现类
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//只有实现了MergedBeanDefinitionPostProcessor接口才执行
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
//执行postProcessMergedBeanDefinition
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
catch (Exception ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing failed of bean type [" + beanType + "] failed", ex);
}
}
复制代码
-
至此,我们对 BeanPostProcessor 有关的源码分析就完成了,小结一下:
-
初始化时,spring 容器有特别处理,会直接调用 beanFactory.addBeanPostProcessor 进行注册(例如 AbstractApplicationContext 类的 prepareBeanFactory 方法中就有);
-
找出所有实现了 BeanPostProcessor 接口的 bean,注册到容器,注册顺序如下:第一:实现了 PriorityOrdered 接口的,排序后;第二:实现了 Ordered 接口的,排序后;第三:既没实现 PriorityOrdered 接口,也没有实现 Ordered 接口的;第四:实现了 MergedBeanDefinitionPostProcessor 接口的(这些也按照 PriorityOrdered、Ordered 等逻辑拍过续);第五:实例化一个 ApplicationListenerDetector 对象;
-
实例化 bean 的时候,对于每个 bean,先用 MergedBeanDefinitionPostProcessor 实现类的 postProcessMergedBeanDefinition 方法处理每个 bean 的定义类;
-
再用 BeanPostProcessor 的 postProcessBeforeInitialization 方法处理每个 bean 实例;
-
bean 实例初始化;
-
用 BeanPostProcessor 的 postProcessAfterInitialization 方法处理每个 bean 实例;
-
源码分析结束,接下来自定义一个 BeanPostProcessor 实现类,验证我们之前的分析:控制 bean 实例;
实战自定义 BeanPostProcessor 实现类
-
本次实战的内容是创建一个 springboot 工程,在里面自定义一个 BeanPostProcessor 接口的实现类,如果您不想敲代码,也可以去 github 下载源码,地址和链接信息如下表所示:
-
这个 git 项目中有多个文件夹,本章源码在文件夹 customizebeanpostprocessor 下,如下图红框所示:
-
接下来开始实战吧:
-
基于 maven 创建一个 springboot 的 web 工程,名为 customizebeanpostprocessor,pom.xml 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>customizebeanpostprocessor</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>customizebeanpostprocessor</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.15.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
复制代码
-
创建 Utils.java,里面有一些静态的工具方法,例如打印当前堆栈:
package com.bolingcavalry.customizebeanpostprocessor.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Utils {
private static final Logger logger = LoggerFactory.getLogger(Utils.class);
/**
* 打印当前线程堆栈信息
* @param prefix
*/
public static void printTrack(String prefix){
StackTraceElement[] st = Thread.currentThread().getStackTrace();
if(null==st){
logger.info("invalid stack");
return;
}
StringBuffer sbf =new StringBuffer();
for(StackTraceElement e:st){
if(sbf.length()>0){
sbf.append(" <- ");
sbf.append(System.getProperty("line.separator"));
}
sbf.append(java.text.MessageFormat.format("{0}.{1}() {2}"
,e.getClassName()
,e.getMethodName()
,e.getLineNumber()));
}
logger.info(prefix
+ "\n************************************************************\n"
+ sbf.toString()
+ "\n************************************************************");
}
}
复制代码
-
创建接口 CalculateService,定义了几个方法:
package com.bolingcavalry.customizebeanpostprocessor.service;
public interface CalculateService {
/**
* 整数加法
* @param a
* @param b
* @return
*/
int add(int a, int b);
/**
* 返回当前实现类的描述信息
* @return
*/
String getServiceDesc();
/**
* 设置当前实现类的描述信息
* @return
*/
void setServiceDesc(String serviceDesc);
}
复制代码
-
创建 CalculateService 的实现类 CalculateServiceImpl,并且用 @Service 注解将定义为 spring 的 bean:
package com.bolingcavalry.customizebeanpostprocessor.service.impl;
import com.bolingcavalry.customizebeanpostprocessor.service.CalculateService;
import org.springframework.stereotype.Service;
@Service("calculateService")
public class CalculateServiceImpl implements CalculateService {
private String serviceDesc = "desc from class";
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public String getServiceDesc() {
return serviceDesc;
}
@Override
public void setServiceDesc(String serviceDesc) {
this.serviceDesc = serviceDesc;
}
}
复制代码
-
注意该类的成员变量 serviceDesc,值已经固定为"desc from class";
-
创建 Controller 类 HelloController,在响应 web 请求的时候,会用到 calculateService 提供的服务:
package com.bolingcavalry.customizebeanpostprocessor.controller;
import com.bolingcavalry.customizebeanpostprocessor.service.CalculateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired(required = false)
CalculateService calculateService;
@GetMapping("/add/{a}/{b}")
public String add(@PathVariable("a") int a, @PathVariable("b") int b){
return "add result : " + calculateService.add(a, b) + ", from [" + calculateService.getServiceDesc() + "]";
}
}
复制代码
-
如上所示,正常情况下,web 响应为"add result : x, from [desc from class]",这个==desc from class==,就是 CalculateServiceImpl 的成员变量 serviceDesc 的值;
-
创建 BeanPostProcessor 的实现类 CustomizeBeanPostProcessor,这里面会修改 calculateService 实例的成员变量 serviceDesc 的值,记得用注解 @Component 将其设置为 bean:
package com.bolingcavalry.customizebeanpostprocessor.processor;
import com.bolingcavalry.customizebeanpostprocessor.service.CalculateService;
import com.bolingcavalry.customizebeanpostprocessor.util.Utils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class CustomizeBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("calculateService".equals(beanName)) {
//打印当前堆栈
Utils.printTrack("do postProcess before initialization");
CalculateService calculateService = (CalculateService)bean;
//修改calculateService实例的成员变量serviceDesc的值
calculateService.setServiceDesc("desc from " + this.getClass().getSimpleName());
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("calculateService".equals(beanName)) {
//打印当前堆栈
Utils.printTrack("do postProcess after initialization");
}
return bean;
}
}
复制代码
-
启动应用,在启动日志中可以看到 CustomizeBeanPostProcessor 实例的两个方法被调用时打印的堆栈日志,和之前我们分析的源码是一致的:
2018-09-02 18:35:53.618 INFO 22520 --- [ main] c.b.c.util.Utils : do postProcess before initialization
************************************************************
java.lang.Thread.getStackTrace() 1,559 <-
com.bolingcavalry.customizebeanpostprocessor.util.Utils.printTrack() 15 <-
com.bolingcavalry.customizebeanpostprocessor.processor.CustomizeBeanPostProcessor.postProcessBeforeInitialization() 14 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization() 409 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean() 1,626 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 555 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 202 <-
org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate() 208 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency() 1,138 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency() 1,066 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject() 585 <-
org.springframework.beans.factory.annotation.InjectionMetadata.inject() 88 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues() 366 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean() 1,272 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 553 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 197 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons() 761 <-
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization() 867 <-
org.springframework.context.support.AbstractApplicationContext.refresh() 543 <-
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh() 122 <-
org.springframework.boot.SpringApplication.refresh() 693 <-
org.springframework.boot.SpringApplication.refreshContext() 360 <-
org.springframework.boot.SpringApplication.run() 303 <-
org.springframework.boot.SpringApplication.run() 1,118 <-
org.springframework.boot.SpringApplication.run() 1,107 <-
com.bolingcavalry.customizebeanpostprocessor.CustomizebeanpostprocessorApplication.main() 10
************************************************************
2018-09-02 18:35:53.619 INFO 22520 --- [ main] c.b.c.util.Utils : do postProcess after initialization
************************************************************
java.lang.Thread.getStackTrace() 1,559 <-
com.bolingcavalry.customizebeanpostprocessor.util.Utils.printTrack() 15 <-
com.bolingcavalry.customizebeanpostprocessor.processor.CustomizeBeanPostProcessor.postProcessAfterInitialization() 24 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization() 423 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean() 1,638 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 555 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 202 <-
org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate() 208 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency() 1,138 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency() 1,066 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject() 585 <-
org.springframework.beans.factory.annotation.InjectionMetadata.inject() 88 <-
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues() 366 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean() 1,272 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 553 <-
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 483 <-
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject() 312 <-
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 230 <-
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 308 <-
org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 197 <-
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons() 761 <-
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization() 867 <-
org.springframework.context.support.AbstractApplicationContext.refresh() 543 <-
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh() 122 <-
org.springframework.boot.SpringApplication.refresh() 693 <-
org.springframework.boot.SpringApplication.refreshContext() 360 <-
org.springframework.boot.SpringApplication.run() 303 <-
org.springframework.boot.SpringApplication.run() 1,118 <-
org.springframework.boot.SpringApplication.run() 1,107 <-
com.bolingcavalry.customizebeanpostprocessor.CustomizebeanpostprocessorApplication.main() 10
************************************************************
复制代码
-
在浏览器访问地址:http://localhost:8080/add/1/2,可以看到响应如下图所示,calculateService 的成员变量 serviceDesc 的值已经被 CustomizeBeanPostProcessor 改为==desc from CustomizeBeanPostProcessor==:
-
至此,本次实战就完成了,从 spring 源码分析再到动手实战,我们对 BeanPostProcessor 的扩展有了更深入的认识,也希望这种扩展能帮助您更好的控制 bean 实例为业务需求服务;
欢迎关注 InfoQ:程序员欣宸
- “打脸”谷歌云,说好的超低延迟和可靠性呢?
- 过去的十五年,我们怎样做 IM?
- 转转 K8s 实践:如何解决容器化带来的四大问题
- 企业级证券业务中台探索与实践
- 云原生(十八) | Kubernetes 篇之 Kubernetes(k8s)工作负载
- 【源码解析】MyBatis 整体架构与源码解析
- 见微知著,带你认认数据分析的大门,站在门口感受一下预测的魅力
- 未来是国产操作系统的钻石时代,微内核将成为新的发展方向|对话中兴新支点操作系统崔黎明
- 【React 源码系列】React Hydrate 原理及源码剖析
- 花 31 万元重新设计网站后,我后悔了
- 一文带你打通 Node 流的"任督二脉"
- RT-Thread 记录(七、IPC 机制之邮箱、消息队列)
- 开发人员应该知道的零信任模型
- 大佬,还记得设计模式的六大设计原则吗?
- Java 参数传递到底是按 值传递 还是 引用传递 ?
- 数据技术大融合,HSTAP 数据库有多少想象空间?
- 说了半天跨平台,今儿咱就来跨跨!(完结篇)——Kubernetes 上手实践
- 我认为前端的职责可能需要重新划分
- 使用 External Secrets Operator 管理 Kubernetes 的 Secret
- Android 应用安全机制实现方案探究