当前位置:首页 > 编程笔记 > 正文
已解决

Spring扩展 BeanDefinitionRegistryPostProcessor详解

来自网友在路上 187887提问 提问时间:2023-10-23 05:10:22阅读次数: 87

最佳答案 问答题库878位专家为你答疑解惑

1、简介

2、概念

2.1 基本介绍

2.1.1  BeanDefinitionRegistryPostProcessor 它是Spring框架的一个扩展点,用于对Bean定义的注册过程进行干预和定制。

2.1.2  BeanDefinitionRegistryPostProcessor 它继承BeanFactoryPostProcessor接口,并在其基础上扩展了一个新的方法,即:postProcessBeanDefinitionRegistry()方法。

2.2 用途

BeanDefinitionRegistryPostProcessor 在Spring容器初始化时,首先会读取应用程序中的配置文件,并解析出所有的Bean定义,然后将这些Bean定义注册到容器中。

在这个过程中,BeanDefinitionRegistryProcessor提供了一种机制,允许开发人员在Bean定义注册之前和之后对Bean定义进行自定义处理,例如添加,修改或删除Bean定义等

2.3 具体原理

具体来说,BeanDefinitionRegistryPostProcessor提供了以下两个方法:

2.3.1  postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry):

该方法在所有Bean定义加载完成之后,Bean实例化之前被调用,允许开发人员对Bean定义进行自定义修改,例如添加,修改或删除Bean定义等。

2.3.2  postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory):

该方法是继承自BeanFactoryPostProcessor接口的方法,用于在BeanFactory完成实例化之后对BeanFactory进行后置处理。
那么我们通过BeanDefinitionRegistryPostProcessor接口,开发人员可以在Spring容器启动时干预Bean的注册过程,从而实现对Bean的自定义处理。

3、调用demo

3.1  案例一

3.1.1  Entity 类 (MyBean)

public class MyBean {private String message = "Hello, World!";public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

3.1.2  手写一个接口

这个接口实现BeanDefinitionRegistryPostProcessor和接口PriorityOrdered,在postProcessBeanDefinitionRegistry方法中对bean的操作进行增删查改

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {/*** 重写BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法*/@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {// 创建一个RootBeanDefinition实例,该实例对应的BeanClass是MyBeanRootBeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);// 向BeanDefinitionRegistry注册MyBean的BeanDefinitionregistry.registerBeanDefinition("myBean", beanDefinition);// 查询和修改BeanDefinition myBean = registry.getBeanDefinition("myBean");System.out.println(myBean);// 删除registry.removeBeanDefinition("myBean");}/*** 重写BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法*/@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}@Overridepublic int getOrder() {return 1;}
}

3.1.3  启动类

@SpringBootApplication
public class FactorybeanDemoApplication {public static ConfigurableApplicationContext context ;public static void main(String[] args) {context = SpringApplication.run(FactorybeanDemoApplication.class, args);MyBean bean = context.getBean(MyBean.class);System.out.println("================"+bean.getMessage()+"===================");}
}
  • 上述代码会抛出No qualifying bean异常,因为我们把myBean的bd删除了
Exception in thread "restartedMain" java.lang.reflect.InvocationTargetExceptionat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.factorybean.factorybeandemo.factorybean.test.MyBean' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)at com.factorybean.factorybeandemo.FactorybeanDemoApplication.main(FactorybeanDemoApplication.java:17)... 5 more
  • 注释掉“registry.removeBeanDefinition("myBean");” 就可以执行成功
2023-10-22 14:43:22.448  INFO 73304 --- [  restartedMain] c.f.f.FactorybeanDemoApplication         : Started FactorybeanDemoApplication in 1.333 seconds (JVM running for 1.87)
================Hello, World!===================

3.2  案例二

3.2.1   配置类 (MyPostBeanRegistar)

@Configuration
public class MyPostBeanRegistar implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {System.out.println("postProcessBeanDefinitionRegistry is invoked");String clzz= Base.class.getName();for(int i=0;i<2;i++){if(!beanDefinitionRegistry.containsBeanDefinition(i+""))ResgistarUtils.registerBeanDefinations(i+"",clzz,beanDefinitionRegistry);}}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {System.out.println("postProcessBeanFactory is invoked");}
}

3.2.2  注册Utils类 (ResgistarUtils)

public class ResgistarUtils {/*** 注册工具类方法* @param className* @param clzz* @param beanDefinitionRegistry*/public static void  registerBeanDefinations(String className, String clzz, BeanDefinitionRegistry beanDefinitionRegistry){/*** 通过 工厂方法来注入Bean*/BeanDefinitionBuilder builder= BeanDefinitionBuilder.genericBeanDefinition(MyfactoryBean.class);builder.addPropertyValue("type",clzz);builder.addPropertyValue("name",className);builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();if(className.equals("0")) {beanDefinition.setPrimary(true);}else{//beanDefinition.s}BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className);BeanDefinitionReaderUtils.registerBeanDefinition(holder, beanDefinitionRegistry);}
}

3.2.3   工厂bean接口实现

public class MyfactoryBean implements FactoryBean<Object> {public Class<?> getType() {return type;}public void setType(Class<?> type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}private Class<?> type;private String name;@Overridepublic Object getObject() throws Exception {System.out.println("getObject");if(this.name.equals("0")){return new TestA();}else if(this.name.equals("1")){return new TestB();}throw new ClassNotFoundException("not found Base by name=["+name+"]");}@Overridepublic Class<?> getObjectType() {return type;}}

3.2.4  Entity 类 (Base、TestA、TestB)

public interface Base {void print();
}
public class TestA implements Base {public TestA(){System.out.println("TestA 够着");}@Overridepublic void print() {System.out.println("testA aaa");}
}
public class TestB implements Base {public TestB(){System.out.println("TestB 够着");}@Overridepublic void print() {System.out.println("testB bbbb ");}
}

3.2.5  测试 Controller 类 (TestController)

@RestController
public class TestController {@AutowiredBase base1;//    @Autowired
//    @Qualifier("1")@Resource(name = "1")Base base2;@GetMapping("/testprint")public String print(){base1.print();base2.print();return "testprint";}
}

3.2.6  启动类

@SpringBootApplication
public class FactorybeanDemoApplication {public static ConfigurableApplicationContext context ;public static void main(String[] args) {context = SpringApplication.run(FactorybeanDemoApplication.class, args);TestA testA = (TestA)context.getBean("0");testA.print();TestB testB = (TestB)context.getBean("1");testB.print();}
}

3.3  统一 pom

<?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.factorybean</groupId><artifactId>factorybean-demo</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>factorybean-demo</name><description>factorybean注入方式 project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.0.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-devtools</artifactId><scope>runtime</scope></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>

4、源码分析

5、参考文献

https://zhuanlan.zhihu.com/p/653695574

https://blog.csdn.net/u014365523/article/details/118683004

https://blog.csdn.net/f5465245/article/details/123551991

https://blog.csdn.net/qq_22986265/article/details/112791601

https://www.cnblogs.com/zhouzhongqing/p/15182101.html

查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"Spring扩展 BeanDefinitionRegistryPostProcessor详解":http://eshow365.cn/6-22179-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!