springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor

简介: springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor

目录:


入门springboot前,先了解spring的下面这三个接口扩展,很有必要。

先看下脑图:

1dc618a0ed9580ce8bfa6facb208c08f.png


1.BeanPostProcessor


这个接口上篇文章讲过,spring利用这个接口,只要实现ApplicationContextWare接口,就可以在此接口,获取springcontext.

他的主要作用也就是:在bean初始化时 搞点小动作:


举例演示:


注入一个bean:


@Component
public class User {
    @PostConstruct
    public void init(){
        System.out.println("===user init==");
    }
}


实现BeanPostProcessor接口,这个接口会影响所有的bean初始化。


@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("=========postProcessBeforeInitialization========"+bean.getClass());
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("=========postProcessAfterInitialization========"+bean.getClass());
        return bean;
    }
}


测试:


public class App2 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
        System.out.println(User.class);
        context.close();
    }
}


运行结果:可以看出什么?在bean初始化前后都打印了。

5d4c6812c8535adbb050f4ddf2e1bce8.png


2.MyBeanFactoryPostProcessor


有了bean初始化时,进行一些小动作,那么容器初始化时是不是可以做一些小动作呢?可以。


这个就是BeanFactoryPostProcessor接口。


BeanFactoryPostProcessor在spring容器初始化之后触发,而且只会触发一次.

我们实现下这个接口:


@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("=================="+ beanFactory.getBeanDefinitionCount());
    }
}


运行结果:

1dc618a0ed9580ce8bfa6facb208c08f.png


显示容器预先注入了8个对象,也就是,这个spring在背后注入了其他的bean。我们就可以在postProcessBeanFactory()方法中,在容器初始化时做一些业务操作。

特别注意: 仅仅会触发一次这个方法。


3.BeanDefinitionRegistryPostProcessor


刚才的那个方法,我们可以在容器初始化时,做一些事情,比如我们通过

beanFactory.getBeanDefinitionCount()获取初始化bean的个数,但是能不能再这里注入一些bean呢?


可以的。


不过得用到BeanFactoryPostProcessor的一个子接口:

5d4c6812c8535adbb050f4ddf2e1bce8.png

这个类扩展了一个方法:

46a9d80a6e05e4e3b19d57a0ee70bcdf.png

里面有个参数BeanDefinitionRegistry.这个类可以帮我们注入一些bean的操作。

66ba272a0bfc97be54a5fa679e3d5482.png

通过上面的registerBeanDefinition的方法。可以注入bean。


下面的removeBeanDefinition可以移除bean。


代码演示:


我们实现这个BeanDefinitionRegistryPostProcessor接口注入10个Person对象:


public class Person {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}


注意Person没有加@Component。


我们用容器注入:


@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        for (int i=1;i<=10;i++){
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
            bdb.addPropertyValue("name","admin"+i);
            registry.registerBeanDefinition("person"+i, bdb.getBeanDefinition());
        }
    }
}


测试类:


public class App2 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
        context.getBeansOfType(Person.class).values().forEach(System.out::println);
        context.close();
    }
}


打印结果:

1dc618a0ed9580ce8bfa6facb208c08f.png

显示注入了。


扩展:也可以用AnnotationConfigApplicationContext注入


public class App2 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
        for (int i=1;i<=10;i++){
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
            bdb.addPropertyValue("name","admin"+i);
            context.registerBeanDefinition("person"+i, bdb.getBeanDefinition());
        }
        context.getBeansOfType(Person.class).values().forEach(System.out::println);
        context.close();
    }
}


运行结果:

5d4c6812c8535adbb050f4ddf2e1bce8.png

为什么AnnotationConfigApplicationContext也可以注入bean呢?

46a9d80a6e05e4e3b19d57a0ee70bcdf.png66ba272a0bfc97be54a5fa679e3d5482.png


通过观察我们发现。AnnotationConfigApplicationContext是BeanDefinitionRegistry子接口的子接口。所以可以调用BeanDefinitionRegistry的所有方法!!


相关文章
|
2月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
410 2
|
3月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
2474 1
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
存储 JSON Java
522 0
|
4月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
757 3
|
9月前
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
477 0
|
9月前
|
安全 Java 数据安全/隐私保护
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
351 0
|
9月前
|
消息中间件 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——发布/订阅消息的生产和消费
本文详细讲解了Spring Boot中ActiveMQ的发布/订阅消息机制,包括消息生产和消费的具体实现方式。生产端通过`sendMessage`方法发送订阅消息,消费端则需配置`application.yml`或自定义工厂以支持topic消息监听。为解决点对点与发布/订阅消息兼容问题,可通过设置`containerFactory`实现两者共存。最后,文章还提供了测试方法及总结,帮助读者掌握ActiveMQ在异步消息处理中的应用。
423 0
|
9月前
|
消息中间件 网络协议 Java
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ集成
本文介绍了在 Spring Boot 中集成 ActiveMQ 的详细步骤。首先通过引入 `spring-boot-starter-activemq` 依赖并配置 `application.yml` 文件实现基本设置。接着,创建 Queue 和 Topic 消息类型,分别使用 `ActiveMQQueue` 和 `ActiveMQTopic` 类完成配置。随后,利用 `JmsMessagingTemplate` 实现消息发送功能,并通过 Controller 和监听器实现点对点消息的生产和消费。最后,通过浏览器访问测试接口验证消息传递的成功性。
582 0

热门文章

最新文章