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的所有方法!!


相关文章
|
3天前
|
XML Java 开发者
Spring Boot开箱即用可插拔实现过程演练与原理剖析
【11月更文挑战第20天】Spring Boot是一个基于Spring框架的项目,其设计目的是简化Spring应用的初始搭建以及开发过程。Spring Boot通过提供约定优于配置的理念,减少了大量的XML配置和手动设置,使得开发者能够更专注于业务逻辑的实现。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,为开发者提供一个全面的理解。
13 0
|
7天前
|
Java Spring
SpringBoot自动装配的原理
在Spring Boot项目中,启动引导类通常使用`@SpringBootApplication`注解。该注解集成了`@SpringBootConfiguration`、`@ComponentScan`和`@EnableAutoConfiguration`三个注解,分别用于标记配置类、开启组件扫描和启用自动配置。
44 17
|
18天前
|
Java 开发者 Spring
精通SpringBoot:16个扩展接口精讲
【10月更文挑战第16天】 SpringBoot以其简化的配置和强大的扩展性,成为了Java开发者的首选框架之一。SpringBoot提供了一系列的扩展接口,使得开发者能够灵活地定制和扩展应用的行为。掌握这些扩展接口,能够帮助我们写出更加优雅和高效的代码。本文将详细介绍16个SpringBoot的扩展接口,并探讨它们在实际开发中的应用。
36 1
|
25天前
|
存储 安全 Java
|
25天前
|
存储 算法 安全
SpringBoot 接口加密解密实现
【10月更文挑战第18天】
|
28天前
|
Java Spring 容器
springboot @RequiredArgsConstructor @Lazy解决循环依赖的原理
【10月更文挑战第15天】在Spring Boot应用中,循环依赖是一个常见问题,当两个或多个Bean相互依赖时,会导致Spring容器陷入死循环。本文通过比较@RequiredArgsConstructor和@Lazy注解,探讨它们解决循环依赖的原理和优缺点。@RequiredArgsConstructor通过构造函数注入依赖,使代码更简洁;@Lazy则通过延迟Bean的初始化,打破创建顺序依赖。两者各有优势,需根据具体场景选择合适的方法。
51 4
|
1月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
56 2
|
1月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
90 1
|
23天前
|
监控 Java 开发者
掌握SpringBoot扩展接口:提升代码优雅度的16个技巧
【10月更文挑战第20天】 SpringBoot以其简化配置和快速开发而受到开发者的青睐。除了基本的CRUD操作外,SpringBoot还提供了丰富的扩展接口,让我们能够更灵活地定制和扩展应用。以下是16个常用的SpringBoot扩展接口,掌握它们将帮助你写出更加优雅的代码。
42 0
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
144 1