写点什么

spring4.1.8 扩展实战之七:控制 bean(BeanPostProcessor 接口)

作者:程序员欣宸
  • 2022 年 6 月 18 日
  • 本文字数:14121 字

    阅读完需:约 46 分钟

spring4.1.8扩展实战之七:控制bean(BeanPostProcessor接口)

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


  • 本章是《spring4.1.8 扩展实战》的第七篇,我们来尝试在容器初始化的时候对 bean 实例做设置;

控制 bean 的两种扩展方式

  • 两种方式可以对 bean 做控制(例如修改某个成员变量)


  1. 改变 bean 的定义(BeanFactoryPostProcessor 接口) ,可以想象成修改了 class 文件,这样实例化出来的每个对象都变了;

  2. 只改变实例化的对象(BeanPostProcessor 接口);


本章概览

  • 全文由以下部分组成:


  1. spring 源码分析,了解 BeanPostProcessor 接口的实现类如何被注册到 spring 容器;

  2. spring 源码分析,了解已经注册到 spring 环境的 BeanPostProcessor 实现类如何被使用;

  3. 实战,开发一个 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 类中,如下所示,==先删除再添加,这样反复注册也没有问题==:


@Overridepublic 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 实例:


@Overridepublic 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:


@Overridepublic 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 有关的源码分析就完成了,小结一下:


  1. 初始化时,spring 容器有特别处理,会直接调用 beanFactory.addBeanPostProcessor 进行注册(例如 AbstractApplicationContext 类的 prepareBeanFactory 方法中就有);

  2. 找出所有实现了 BeanPostProcessor 接口的 bean,注册到容器,注册顺序如下:第一:实现了 PriorityOrdered 接口的,排序后;第二:实现了 Ordered 接口的,排序后;第三:既没实现 PriorityOrdered 接口,也没有实现 Ordered 接口的;第四:实现了 MergedBeanDefinitionPostProcessor 接口的(这些也按照 PriorityOrdered、Ordered 等逻辑拍过续);第五:实例化一个 ApplicationListenerDetector 对象;

  3. 实例化 bean 的时候,对于每个 bean,先用 MergedBeanDefinitionPostProcessor 实现类的 postProcessMergedBeanDefinition 方法处理每个 bean 的定义类;

  4. 再用 BeanPostProcessor 的 postProcessBeforeInitialization 方法处理每个 bean 实例;

  5. bean 实例初始化;

  6. 用 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;
@RestControllerpublic 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;
@Componentpublic 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:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

发布于: 2022 年 06 月 18 日阅读数: 40
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
spring4.1.8扩展实战之七:控制bean(BeanPostProcessor接口)_Java_程序员欣宸_InfoQ写作社区