写点什么

spring4.1.8 扩展实战之六:注册 bean 到 spring 容器 (BeanDefinitionRegistryPostProcessor 接口)

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

    阅读完需:约 39 分钟

spring4.1.8扩展实战之六:注册bean到spring容器(BeanDefinitionRegistryPostProcessor接口)

欢迎访问我的 GitHub

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


  • 本章是《spring4.1.8 扩展实战》系列的第六篇,目标是学习如何通过自己写代码的方式,向 spring 容器中注册 bean;

关于注册 bean 到容器

  • 我们开发的类,如果想注册到 spring 容器,让 spring 来完成实例化,常用方式如下:


  1. xml 中通过 bean 节点来配置;

  2. 使用 @Service、@Controller、@Conponent 等注解;


  • 其实,除了以上方式,spring 还支持我们通过代码来将指定的类注册到 spring 容器中,也就是今天我们要实践的主要内容,接下来就从 spring 源码开始,先学习源码再动手实战;

本章概要

  • 本章由以下几部分组成:


  1. 了解 BeanDefinitionRegistryPostProcessor 接口;

  2. 分析 spring 容器如何使用 BeanDefinitionRegistryPostProcessor 接口;

  3. 实战,开发 BeanDefinitionRegistryPostProcessor 接口的实现类,验证通过代码注册 bean 的功能;

了解 BeanDefinitionRegistryPostProcessor 接口

  • 实现注册 bean 功能的关键是 BeanDefinitionRegistryPostProcessor 接口,来看看这接口的继承关系,如下图:


  • BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor 接口,关于 BeanFactoryPostProcessor 我们在上一章《spring4.1.8扩展实战之五:改变bean的定义(BeanFactoryPostProcessor接口)》已做了详细的分析和实战,知道 BeanFactoryPostProcessor 的实现类在其 postProcessBeanFactory 方法被调用时,可以对 bean 的定义进行控制,因此 BeanDefinitionRegistryPostProcessor 的实现类一共要实现以下两个方法:

  • void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException:该方法的实现中,主要用来对 bean 定义做一些改变,这些在上一章《spring4.1.8扩展实战之五:改变bean的定义(BeanFactoryPostProcessor接口)》有详细说明;

  • void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException:该方法用来注册更多的 bean 到 spring 容器中,详细观察入参 BeanDefinitionRegistry 接口,看看这个参数能带给我们什么能力:


  • 从上图可以看到,为了能让我们通过代码将 bean 注册到 spring 环境,BeanDefinitionRegistry 提供了丰富的方法来操作 bean 定义,判断、注册、反注册等方法都准备好了,我们在编写 postProcessBeanDefinitionRegistry 方法的内容时,就能直接使用入参 registry 的这些方法来完成判断和注册、反注册等操作;

分析 spring 容器如何使用 BeanDefinitionRegistryPostProcessor 接口

  • 来看看 BeanDefinitionRegistryPostProcessor 接口的实现类,是在哪里被 spring 容器使用的:

  • 如下图所示,红框中的 invokeBeanFactoryPostProcessors 方法用来找出所有 beanFactory 后置处理器,并且调用这些处理器来改变 bean 的定义:



  • 打开 invokeBeanFactoryPostProcessors 方法,如下所示,实际操作是委托 PostProcessorRegistrationDelegate 去完成的:


protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());    }
复制代码


  • 继续看 PostProcessorRegistrationDelegate 类的 invokeBeanFactoryPostProcessors 方法,该方法内容太丰富,我们只看重点,第一个重点如下图红框所示,==当前的 beanFactory 是否实现了接口 BeanDefinitionRegistry==:



  • 为了搞清楚这个问题,我们应该看看当前 beanFactory 的继承和实现,以 springboot 中的应用为例,当前 beanFactory 的类型是 DefaultListableBeanFactory,来看看它的类图:



  • 从上图红框可见,beanFactory 实现了 BeanDefinitionRegistry 接口,因此我们的关注点是 if 条件满足后的执行逻辑;

  • 继续看 PostProcessorRegistrationDelegate 类的 invokeBeanFactoryPostProcessors 方法,以下片段就是操作 BeanDefinitionRegistryPostProcessor 的核心逻辑:


boolean reiterate = true;while (reiterate) {  reiterate = false;  //查出所有实现了BeanDefinitionRegistryPostProcessor接口的bean名称  postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);  for (String ppName : postProcessorNames) {    //前面的逻辑中,已经对实现了PriorityOrdered和Ordered的bean都处理过了,因此通过processedBeans过滤,processedBeans中没有的才会在此处理    if (!processedBeans.contains(ppName)) {      //根据名称和类型获取bean      BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);      //把已经调用过postProcessBeanDefinitionRegistry方法的bean全部放在registryPostProcessors中      registryPostProcessors.add(pp);      //把已经调用过postProcessBeanDefinitionRegistry方法的bean的名称全部放在processedBeans中      processedBeans.add(ppName);      //执行此bean的postProcessBeanDefinitionRegistry方法      pp.postProcessBeanDefinitionRegistry(registry);      //改变退出while的条件      reiterate = true;    }  }}
//registryPostProcessors中保存了所有执行过postProcessBeanDefinitionRegistry方法的bean,//现在再来执行这些bean的postProcessBeanFactory方法invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);//regularPostProcessors中保存的是所有入参中带来的BeanFactoryPostProcessor实现类,并且这里面已经剔除了BeanDefinitionRegistryPostProcessor的实现类,现在要让这些bean执行postProcessBeanFactory方法invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
复制代码


  • 如上述代码所示,所有实现了 BeanDefinitionRegistryPostProcessor 接口的 bean,其 postProcessBeanDefinitionRegistry 方法都会调用,然后再调用其 postProcessBeanFactory 方法,这样一来,我们如果自定义了 BeanDefinitionRegistryPostProcessor 接口的实现类,那么我们开发的 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory 方法都会被执行一次;

  • 到这里,我们的源码学习部分就完成了,接下来看开始实战吧;

实战,开发 BeanDefinitionRegistryPostProcessor 接口的实现类

  • 本次实战的内容是创建一个 springboot 工程,在里面自定义一个 BeanDefinitionRegistryPostProcessor 接口的实现类,如果您不想敲代码,也可以去 github 下载源码,地址和链接信息如下表所示:



  • 这个 git 项目中有多个文件夹,本章源码在文件夹 customizebeandefinitionregistrypostprocessor 下,如下图红框所示:



  • 接下来开始实战吧:

  • 基于 maven 创建一个 springboot 的 web 工程,名为 customizebeandefinitionregistrypostprocessor,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>customizebeandefinitionregistrypostprocessor</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>customizebeandefinitionregistrypostprocessor</name> <description>Demo project for customize BeanDefinitionRegistryPostProcessor</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>
复制代码


  • 定义一个服务接口 CalculateService:


package com.bolingcavalry.customizebeandefinitionregistrypostprocessor.service;
public interface CalculateService { /** * 整数加法 * @param a * @param b * @return */ int add(int a, int b);
/** * 返回当前实现类的描述信息 * @return */ String getServiceDesc();}
复制代码


  • 创建 CalculateService 接口的实现类 CalculateServiceImpl,==注意,不要将其声明为 spring 的 bean==:


package com.bolingcavalry.customizebeandefinitionregistrypostprocessor.service.impl;
import com.bolingcavalry.customizebeandefinitionregistrypostprocessor.service.CalculateService;
public class CalculateServiceImpl implements CalculateService {
private String desc = "desc from class";
public void setDesc(String desc) { this.desc = desc; }

@Override public int add(int a, int b) { return a + b; }
@Override public String getServiceDesc() { return desc; }}
复制代码


  • 创建工具类 Utils,里面是些工具方法,例如在日志中打印出当前线程的执行堆栈:


package com.bolingcavalry.customizebeandefinitionregistrypostprocessor.util;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
/** * @Description : 提供一些常用的工具方法 * @Author : zq2599@gmail.com * @Date : 2018-08-14 05:51 */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************************************************************"); }}
复制代码


  • 创建 Controller 类,用于验证我们通过代码注册的 bean,==注意要给成员变量 calculateService 添加注解 @Autowired(required = false),否则有的 IDEAL 上会有红叉提示==:


package com.bolingcavalry.customizebeandefinitionregistrypostprocessor.controller;
import com.bolingcavalry.customizebeandefinitionregistrypostprocessor.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() + "]"; }}
复制代码


  • 创建 BeanDefinitionRegistryPostProcessor 的实现类 CustomizeBeanDefinitionRegistryPostProcessor:


@Componentpublic class CustomizeBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {    @Override    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {  //打印当前堆栈信息            Utils.printTrack("execute postProcessBeanDefinitionRegistry");    //创建一个bean的定义类的对象,bean类型是CalculateServiceImpl        RootBeanDefinition helloBean = new RootBeanDefinition(CalculateServiceImpl.class);
//bean的定义注册到spring环境 beanDefinitionRegistry.registerBeanDefinition("calculateService", helloBean); }
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { //打印当前堆栈信息 Utils.printTrack("execute postProcessBeanFactory"); }}
复制代码


  • 上面 CustomizeBeanDefinitionRegistryPostProcessor 就是我们扩展出来的 BeanDefinitionRegistryPostProcessor 实现类,用来将 CalculateServiceImpl 注册到 spring 容器,名称为 calculateService;

  • 启动类 CustomizebeandefinitionregistrypostprocessorApplication:


package com.bolingcavalry.customizebeandefinitionregistrypostprocessor;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class CustomizebeandefinitionregistrypostprocessorApplication {
public static void main(String[] args) { SpringApplication.run(CustomizebeandefinitionregistrypostprocessorApplication.class, args); }}
复制代码


  • 启动应用,在启动日志中可以看到 CustomizeBeanDefinitionRegistryPostProcessor 的方法被调用时的堆栈情况:


2018-08-30 18:55:40.323  INFO 14880 --- [           main] c.b.c.util.Utils                         : execute postProcessBeanDefinitionRegistry************************************************************java.lang.Thread.getStackTrace() 1,556 <- com.bolingcavalry.customizebeandefinitionregistrypostprocessor.util.Utils.printTrack() 20 <- com.bolingcavalry.customizebeandefinitionregistrypostprocessor.registrypostprocessor.CustomizeBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry() 21 <- org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors() 272 <- org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 122 <- org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors() 687 <- org.springframework.context.support.AbstractApplicationContext.refresh() 525 <- 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.customizebeandefinitionregistrypostprocessor.CustomizebeandefinitionregistrypostprocessorApplication.main() 10************************************************************2018-08-30 18:55:40.542  INFO 14880 --- [           main] c.b.c.util.Utils                         : execute postProcessBeanFactory************************************************************java.lang.Thread.getStackTrace() 1,556 <- com.bolingcavalry.customizebeandefinitionregistrypostprocessor.util.Utils.printTrack() 20 <- com.bolingcavalry.customizebeandefinitionregistrypostprocessor.registrypostprocessor.CustomizeBeanDefinitionRegistryPostProcessor.postProcessBeanFactory() 31 <- org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 283 <- org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 127 <- org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors() 687 <- org.springframework.context.support.AbstractApplicationContext.refresh() 525 <- 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.customizebeandefinitionregistrypostprocessor.CustomizebeandefinitionregistrypostprocessorApplication.main() 10************************************************************
复制代码


  • 在浏览器输入:http://localhost:8080/add/1/2,如下图可以看到网页正常响应,controller 可以正常使用 calculateService 实例:



  • 去掉 CustomizeBeanDefinitionRegistryPostProcessor 的注释 @Component,重启应用,再去访问 http://localhost:8080/add/1/2,可以看到网页提示错误如下图:



  • 看后台日志,是因为 calculateService 这个 bean 为空,导致 HelloController 在响应请求的时候出现了空指针异常,这也再次证明了 CustomizeBeanDefinitionRegistryPostProcessor 的注册操作是有效的:


2018-08-30 19:00:01.186 ERROR 2760 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null at com.bolingcavalry.customizebeandefinitionregistrypostprocessor.controller.HelloController.add(HelloController.java:18) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.18.RELEASE.jar:4.3.18.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.18.RELEASE.jar:4.3.18.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471) [tomcat-embed-core-8.5.32.jar:8.5.32] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.32.jar:8.5.32] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.32.jar:8.5.32] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
复制代码


  • 至此,自定义 bean 注册的实战就结束了,其实除了注册 bean,我们还能利用 BeanDefinitionRegistry 这个入参做些其他事情,例如查找 bean,反注册 bean 等,帮助我们实现一些 bean 操作的业务需求;

欢迎关注 InfoQ:程序员欣宸

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

发布于: 刚刚阅读数: 4
用户头像

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

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

评论

发布
暂无评论
spring4.1.8扩展实战之六:注册bean到spring容器(BeanDefinitionRegistryPostProcessor接口)_Java_程序员欣宸_InfoQ写作社区