先回顾下spring高级容器中最重要的方法refresh:
先构建一个DefaultListableBeanFactory容器实例,内部会注册一次bean;
再调用postProcessBeanFactory方法及invokeBeanFactoryPostProcessors方法,这里是spring的一个扩展点:BeanFactoryPostProcessor接口。因为之前已经注册过一次bean定义了,这里留了一个扩展点,可以补充bean定义也可以修改之前的bean定义。spring中对于@Configuration处理就是使用BeanFactoryPostProcessor的经典案例。
注意BeanFactoryPostProcessor是用于处理bean定义的注册的,而非bean的实例化。
再往后,registerBeanPostProcessors注册beanPostProcessor;
然后是一些国际化;
再往后,finishBeanFactoryInitialization完成非lazy的bean的实例化,里面会调用beanpostprocessor来处理bean的实例化,也是一个扩展点。Spring的@PostConstruct是一个经典例子。
这里主要看下BeanFactoryPostProcessor。
一个小例子:
public class TestBeanFactoryProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] names = beanFactory.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
仅仅打印出当前注册的bean的名字。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="spring.xml.config.TestBeanFactoryProcessor"/>
</beans>
注册该processor。
结果:
cd3
player3
player4
spring.xml.config.TestBeanFactoryProcessor#0
这里没有贴bean的定义。
再看下原理:
refresh的invokeBeanFactoryPostProcessors方法会加载容器内的processor:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
invoke方法的核心逻辑:
String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
/**
* Invoke the given BeanFactoryPostProcessor beans.
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
从容器中加载processor,再逐个调用接口方法。