在上一节中,我们说到了BeanFactory是较为轻量的容器,这个容器启动时会通过BeanDefinitionReader来加载配置文件获得对应BeanDefinition,然后将BeanDefinition注册到BeanDefinitionRegistry。这些是容器启动所做的工作,下一阶段就该实例化了。
如果当前使用的容器是BeanFactory,那么在getBean()时才会实例化;
如果使用ApplicationContext,如果bean的scope是singleton的,并且lazy-init为false(默认是false,所以可以不用设置),则ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候,直接从这个缓存中取;如果bean的scope是singleton的,并且lazy-init为true,则该Bean的实例化是在第一次使用该Bean的时候进行实例化;如果bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化
OK,弄明白上边两个阶段后,我们引入今天的话题,容器的扩展机制。BeanFactoryProcessor允许我们在上述第一个阶段结束对最后生成BeanDefinition做出修改。
public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException; } 复制代码
BeanFactoryProcessor接口很简单,只有一个方法,方法名字也很显义,即BeanFactory的后处理工作,那么参数中的BeanFactory就是我们要处理的BeanFactory了。
// 这里我们使用BeanFactory的子接口 public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException; } // 定义了一个继承自BeanDefinitionRegistryPostProcessor的处理器,作用是创建student的BeanDefinition并进行注册 public class BfProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // 第一次从所有befinition中找不到student System.out.println(registry.getBeanDefinition("student")); // 创造student的beandefinition BeanDefinitionHolder holder = createBeanDefinition(Student.class.getName()); // 注册 BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); // 此时有了 System.out.println(registry.getBeanDefinition("student")); } // 生产student的beandefinition private BeanDefinitionHolder createBeanDefinition(String className) { BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(Student.class); definition.addPropertyValue("name", "ffbbb"); return new BeanDefinitionHolder(definition.getBeanDefinition(), "student"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } } 复制代码
我们在上边这段代码中定义了一个继承自 BeanDefinitionRegistryPostProcessor 的后处理器 BfProcessor,将它注册到容器中
@Configuration public class config { @Bean public User user(){ return new User(100,"bbf"); } @Bean public BfProcessor bfProcessor(){ return new BfProcessor(); } } @Data public class Student { private String name; } 复制代码
同时可以看到,我们并没有把Student进行注册,所以正常情况下容器初始化完成不会有Student的,接着, 我们的后处理器开始发挥作用,在第一遍扫描不到student后开始生产student的beandefinition,然后注册到registry,所以第二次扫描时可以扫描到student的beandefinition,此时的beandefinition只是元数据,并没有被实例化还,正如我们前面说过的,还没到实例化的阶段,底下这一长行就是该beandefinition。
Generic bean: class [com.example.springdemo.Bean.Student]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null 复制代码
一个很简单的小例子,我们可以看到BeanFactoryProcessor中主要是针对beandefinition做一些工作,同时注意不要混淆BeanDefinition和真正的bean。