文章目录

  • SpringBoot
  • SpringBoot 原理篇
  • 1 自动配置
  • 1.10 bean 的加载方式【八】
  • 1.10.1 BeanDefinitionRegistryPostProcessor
  • 1.10.2 小结


1 自动配置

1.10 bean 的加载方式【八】
1.10.1 BeanDefinitionRegistryPostProcessor

之前我们又使用 ImportBeanDefinitionRegistrar 接口来实现了bean 的加载

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_java

比ImportSelector 接口更高端了些,【还有吗?】【还有第八种】

来个新的类

package com.dingjiaxiong.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

/**
 * ClassName: MyPostProcessor
 * date: 2022/10/24 16:41
 *
 * @author DingJiaxiong
 */


public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        //后处理bean 定义注册,参数和第七种那个注册一样
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("yellow",beanDefinition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

可以看到,它和第七种特别像,直接把第七种贴过来都能用了,问题就有了, 为啥叫什么后处理?

一点一点来

先来一个配置类

package com.dingjiaxiong.config;

import com.dingjiaxiong.bean.MyRegistrar;
import com.dingjiaxiong.service.impl.BookServiceImpl1;
import org.springframework.context.annotation.Import;

/**
 * ClassName: SpringConfig8
 * date: 2022/10/24 14:52
 *
 * @author DingJiaxiong
 */

@Import(BookServiceImpl1.class)
public class SpringConfig8 {
}

这个图书实现类,已经是好久之前的了,笔者这里再贴一下

package com.dingjiaxiong.service.impl;

import com.dingjiaxiong.service.BookService;

/**
 * ClassName: BookServiceImpl1
 * date: 2022/10/24 10:35
 *
 * @author DingJiaxiong
 */


public class BookServiceImpl1 implements BookService {
    
    @Override
    public void check() {
        System.out.println("book service 1...");
    }
}

OK,再来个运行类

package com.dingjiaxiong.app;

import com.dingjiaxiong.config.SpringConfig7;
import com.dingjiaxiong.config.SpringConfig8;
import com.dingjiaxiong.service.BookService;
import com.dingjiaxiong.service.impl.BookServiceImpl1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * ClassName: App8
 * date: 2022/10/24 13:42
 *
 * @author DingJiaxiong
 */

public class App8 {

    public static void main(String[] args) {

        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig8.class);
        BookService bookService = ctx.getBean("bookService", BookService.class);

        bookService.check();
    }

}

修改一下实现类,把它定义成一个bean

package com.dingjiaxiong.service.impl;

import com.dingjiaxiong.service.BookService;
import org.springframework.stereotype.Service;

/**
 * ClassName: BookServiceImpl1
 * date: 2022/10/24 10:35
 *
 * @author DingJiaxiong
 */

@Service("bookService")
public class BookServiceImpl1 implements BookService {

    @Override
    public void check() {
        System.out.println("book service 1...");
    }
}

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_spring boot_02

现在结构就很清晰了,所有都在针对实现类1

OK,直接运行

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_加载_03

调用成功【这和第八种方法暂时没关系,就只是一个简单的bean 调用】

接下来加上我们写的类

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_加载_04

并且修改一下这个类

package com.dingjiaxiong.bean;

import com.dingjiaxiong.service.impl.BookServiceImpl2;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

/**
 * ClassName: MyRegistrar
 * date: 2022/10/24 16:24
 *
 * @author DingJiaxiong
 */


public class MyRegistrar implements ImportBeanDefinitionRegistrar {


    //第一个参数就是我们之前看的元数据,而且他还有一个参数,也就是这种方式比第六种更强大
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        //1. 使用元数据进行判定【这里就不判了】
        //初始化BeanDefinition对象
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl2.class).getBeanDefinition();

        registry.registerBeanDefinition("bookService",beanDefinition);
    }
}

也就是说,我现在本身导了个 1 ,但是又用ImportBeanDefinitionRegistrar 导了个2

直接运行看看结果

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_spring_05

结果很明显,它既没报错, 而且调用了实现类2的方法

实现类2 BookServiceImpl2

现在的意思就是1 被覆盖了,好家伙

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_spring boot_06

这样子的意义是什么?前面的1 就是默认技术【比如内嵌的Tomcat、内嵌的数据源…】

而后面就是我们自己定义了一个【那万一项目组人多】

举个栗子

package com.dingjiaxiong.bean;

import com.dingjiaxiong.service.impl.BookServiceImpl2;
import com.dingjiaxiong.service.impl.BookServiceImpl3;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

/**
 * ClassName: MyRegistrar2
 * date: 2022/10/24 16:24
 *
 * @author DingJiaxiong
 */


public class MyRegistrar2 implements ImportBeanDefinitionRegistrar {


    //第一个参数就是我们之前看的元数据,而且他还有一个参数,也就是这种方式比第六种更强大
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        //1. 使用元数据进行判定【这里就不判了】
        //初始化BeanDefinition对象
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl3.class).getBeanDefinition();

        registry.registerBeanDefinition("bookService",beanDefinition);
    }
}

现在的情况就是,有两个开发者,都对同一个技术进行了实现,然后!很巧的是

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_加载_07

它俩都摆在了这儿,现在会是谁生效,直接运行

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_ide_08

妙了,3 生效了

挪下位置

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_java_09

OK,效果很明显,和加载顺序有关【现在真正的问题来了,现在是配置的顺序说了算,没有东西能够管一下它俩?万一以后更多,那不乱死?】

OK,第八种加载方式就是干这事儿的

把它也加上

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_加载_10

package com.dingjiaxiong.bean;

import com.dingjiaxiong.service.impl.BookServiceImpl4;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

/**
 * ClassName: MyPostProcessor
 * date: 2022/10/24 16:41
 *
 * @author DingJiaxiong
 */


public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        //后处理bean 定义注册,参数和第七种那个注册一样
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl4.class).getBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("bookService",beanDefinition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

这个加载的4 ,OK,终局之战

直接运行

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_spring boot_11

MyPostProcessor说了算

这就是“后” 的意义,前面的全整完之后,我一来,前面的全部没用 了

【这种后处理的机制有什么用?】

保障性工作

这就是它最牛的地方

OK,回顾一下

导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,
实现对容器中bean的最终裁定

springboot 哪里加载 AbstractAnnotationConfigDispatcherServletInitializer springboot如何加载bean_java_12

其实还有加载方式,但是这些够用了

1.10.2 小结
  1. xml+<bean/>
  2. xml:context+注解(@Component+4个@Bean)
  3. 配置类+扫描+注解(@Component+4个@Bean)
  • @Bean定义FactoryBean接口
  • @ImportResource
  • @Configuration注解的proxyBeanMethods属性
  1. @Import导入bean的类
  • @Import导入配置类
  1. AnnotationConfigApplicationContext调用register方法
  2. @Import导入ImportSelector接口
  3. @Import导入ImportBeanDefinitionRegistrar接口
  4. @Import导入BeanDefinitionRegistryPostProcessor接口