目标:我们学习spring的源码的主要目的: 对bean的扩展
package com.springbeanDemo.config;
import com.springbeanDemo.pojo.Product;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
/**
* 注释
*
* @author sunhao
* @Date 2021-08-09-20:49
*/
@Component
public class springBeanFactory implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
final GenericBeanDefinition bean = (GenericBeanDefinition) configurableListableBeanFactory.getBeanDefinition("bean1");
bean.setBeanClass(Bean2.class);
}
}
1.我们需要实现BeanFactoryPostProcessor接口的postProcessBeanFactory方法 他会有一个 ConfigurableListableBeanFactory类型的参数configurableListableBeanFactory 就是我们常说的spring工厂。
2.这个工厂中存在一个map
💣注意这里说的不是单例池的map
上一篇文章讲到过 在Bean初始化的过程中会把属性都注入到BeanFactoryDefinition对象,然后再把BeanFactoryDefinition对象放入到一个map中,从这里就得到了证实。beanDefinitionMap
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
} else {
return bd;
}
}
3.对bean的扩展
final GenericBeanDefinition bean = (GenericBeanDefinition) configurableListableBeanFactory.getBeanDefinition("bean1");
bean.setBeanClass(Bean2.class);
在这里通过名字configurableListableBeanFactory.getBeanDefinition("bean1");
去找到这个BeanFactoryDefinition对象然后 这里是重点bean.setBeanClass(Bean2.class);
他把另外一个类 Bean2.class 放到里面 这时候 Bean1.class就不存在在我们的工厂里面了
package com;
import com.springbeanDemo.config.Config;
import com.springbeanDemo.pojo.Product;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 注释
* 验证是不是置换了value 用原来的key还能取到
* @author sunhao
* @Date 2021-08-09-20:46
*/
public class Main {
public static void main(String[] args) {
final AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
System.out.println(ac.getBean(Bean2.class));
System.out.println(ac.getBean("bean1"));
System.out.println(ac.getBean(Bean2.class) == ac.getBean("bean1"));
}
}
请记住这里的ac.getBean(“bean1”)会产生疑惑 他取出来的是Bean2.class
我们通过ac.getBean(Bean2.class) 和 ac.getBean(“bean1”) 获取到的对象是同一个 都是Bean2.class 这里验证了 bean.setBeanClass(Bean2.class);
只是把beanClass 这个属性换了。他到了创建bean的那一步就会根据Bean2.class反射去寻找类
我们如果想通过ac.getBean("bean2")
获取到这个Bean2.class的话 需要加上
bean.setBeanClassName(“bean2”);
@Component
public class springBeanFactory implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
final GenericBeanDefinition bean = (GenericBeanDefinition) configurableListableBeanFactory.getBeanDefinition("bean1");
bean.setBeanClass(Bean2.class);
bean.setBeanClassName("bean2");
}
}
@Component这个类上加上扫描注解才会生效
总结:
这里还没有到创建对象的那一步,上一篇文章中说过 对BeanFactoryDefinition扩展完成后 他会根据BeanFactoryDefinition中的属性决定是否去立即创建bean
这里可以理解为 他现在更改的是创建bean之前的那个模板
更改后他就会根据更改之后的模板去创建这个bean到单例池map中