发
2.1.1 BeanDefinitionRegistryPostProcessor 它是Spring框架的一个扩展点,用于对Bean定义的注册过程进行干预和定制。
2.1.2 BeanDefinitionRegistryPostProcessor 它继承BeanFactoryPostProcessor接口,并在其基础上扩展了一个新的方法,即:postProcessBeanDefinitionRegistry()方法。
BeanDefinitionRegistryPostProcessor 在Spring容器初始化时,首先会读取应用程序中的配置文件,并解析出所有的Bean定义,然后将这些Bean定义注册到容器中。
在这个过程中,BeanDefinitionRegistryProcessor提供了一种机制,允许开发人员在Bean定义注册之前和之后对Bean定义进行自定义处理,例如添加,修改或删除Bean定义等。
具体来说,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.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方法
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 创建一个RootBeanDefinition实例,该实例对应的BeanClass是MyBean
RootBeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);
// 向BeanDefinitionRegistry注册MyBean的BeanDefinition
registry.registerBeanDefinition("myBean", beanDefinition);
// 查询和修改
BeanDefinition myBean = registry.getBeanDefinition("myBean");
System.out.println(myBean);
// 删除
registry.removeBeanDefinition("myBean");
}
/**
* 重写BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public 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()+"===================");
}
}
Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
at 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' available
at 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
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.1 配置类 (MyPostBeanRegistar)
@Configuration
public class MyPostBeanRegistar implements BeanDefinitionRegistryPostProcessor {
@Override
public 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);
}
}
@Override
public 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
3.2.4 Entity 类 (Base、TestA、TestB)
public interface Base {
void print();
}
public class TestA implements Base {
public TestA(){
System.out.println("TestA 够着");
}
@Override
public void print() {
System.out.println("testA aaa");
}
}
public class TestB implements Base {
public TestB(){
System.out.println("TestB 够着");
}
@Override
public void print() {
System.out.println("testB bbbb ");
}
}
3.2.5 测试 Controller 类 (TestController)
@RestController
public class TestController {
@Autowired
Base 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
4.0.0
com.factorybean
factorybean-demo
0.0.1-SNAPSHOT
jar
factorybean-demo
factorybean注入方式 project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
2.1.0.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-devtools
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
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