Spring 中常用的手动装载 bean 方法

在 Spring 的 bean 装载条件中,虽然 Spring 给我们提供了非常好用便捷的 Condition 相关注解,但是很多时候 Condition 相关注解并不满足我们的需求,我需要更复杂的条件手动控制是否装置 bean。这个时候我们就可以实现 Spring 为我们提供的几个接口来实现手动 bean 的注入。

一、ApplicationContextAware 接口

在某些特殊的情况下,bean 需要实现某个功能,但该功能必须借助于 Spring 容器才能实现,此时就必须让该 bean 先获取 Spring 容器,然后借助于 Spring 容器实现该功能。为了让 bean 获取它所在的 Spring 容器,可以让该 bean 实现 ApplicationContextAware 接口。ApplicationContextAware 通过它 Spring 容器会自动把上下文环境对象调用ApplicationContextAware 接口中的 setApplicationContext 方法。在 ApplicationContextAware 的实现类中,就可以通过这个上下文环境对象得到 Spring 容器中的 bean。

java 复制代码
@Component
public class MyContextAware implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("SpringWebSocketContextAware");
        // 将 applicationContext 转换为 ConfigurableApplicationContext
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;

        // 获取 BeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getAutowireCapableBeanFactory();

        // 创建 bean 信息
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Test.class);

        // 动态注册 bean
        defaultListableBeanFactory.registerBeanDefinition("test", beanDefinitionBuilder.getBeanDefinition());
    }
}

二、BeanDefinitionRegistryPostProcessor 接口

Spring 中并没有具体去实现 postProcessBeanFactory 方法,是提供给想要实现BeanPostProcessor 的三方框架使用的。谁要使用谁就去实现。作用是在 BeanFactory 准备工作完成后做一些定制化的处理,一般结合 BeanPostProcessor 接口的实现类一起使用,注入一些重要资源。

java 复制代码
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Test.class).getBeanDefinition();
        registry.registerBeanDefinition("test", beanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinitionRegistryPostProcessor.super.postProcessBeanFactory(beanFactory);
    }
}

三、ImportBeanDefinitionRegistrar 接口

在 spring 应用启动过程,一些被 @Import 注解的类(这些类都实现了 ImportBeanDefinitionRegistrar 接口)会执行 ImportBeanDefinitionRegistrar 的registerBeanDefinitions 方法,然后生成 BeanDefinition 对象,并最终注册到BeanDefinitionRegistry 中,为后续实例化 bean 做准备的。

java 复制代码
@Component
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(@NotNull AnnotationMetadata importingClassMetadata,
                                        @NotNull BeanDefinitionRegistry registry,
                                        @NotNull BeanNameGenerator importBeanNameGenerator) {
        this.registerBeanDefinitions(importingClassMetadata, registry);
    }

    @Override
    public void registerBeanDefinitions(@NotNull AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry) {
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Test.class)
                .getBeanDefinition();
        registry.registerBeanDefinition("test", beanDefinition);
        ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry);
    }
}

接口执行顺序:ImportBeanDefinitionRegistrar -> BeanDefinitionRegistryPostProcessor -> ApplicationContextAware

相关推荐
冬夜戏雪3 分钟前
[学习日记][springboot 1-7][leetcode 6道]
java·开发语言·学习
讓丄帝愛伱4 分钟前
idea 中 mapper.xml黄线警告怎么去掉
java·intellij-idea
桦说编程15 分钟前
线程池拒绝策略避坑:谨慎使用抛弃策略,可能导致系统卡死
java·后端
奋斗的小monkey15 分钟前
Java微服务实战:从零搭建电商用户服务系统
java·spring boot·微服务·nacos·电商系统·redis缓存
菜鸟plus+17 分钟前
URL 设计
java
星秀日21 分钟前
框架--MyBatis
java·开发语言·mybatis
没有bug.的程序员31 分钟前
分布式缓存架构:从原理到生产实践
java·分布式·缓存·架构·分布式缓存架构
_hermit:34 分钟前
【从零开始java学习|第二十二篇】集合进阶之collection
java·学习
锥栗37 分钟前
【Redis】【缓存】理解缓存三大问题:缓存穿透、缓存击穿与缓存雪崩及解决方案
java·后端·面试
9号达人38 分钟前
泛型+函数式:让策略模式不再是复制粘贴地狱
java·后端·面试