概述一下
springframework有很多创建SpringBean的方式,所谓SpringBean就是被spring生命周期管理的bean。比如@Component,@Service等注解的Class,在Spring启动时,都会逐步生成SpringBean,并且被spring容器管理。
在@Configuration注解的配置类里,通过被@Bean注解的方法,也能生成SpringBean。
如:
@Configuration
@ComponentScan("org.dhframework")
public class Appconfig {
@Bean
public WanDouBean xyz() {
System.out.println("通过xyz()创建WanDouBean");
return new WanDouBean();
}
}
分析一下
把一个类纳入spring来管理,需要主要2个大步骤(个人理解这2个步骤很重要)。
第一,生成这个类相关的BeanDefinition(bd),把该bd放到BeanDefinitionMap(bdMap)里。
第二,从bdMap把该bd捞出啦,然后生成SpringBean,放入singletonObjects(是个map)里。
- 如何生成bd?
AbstractApplicationContext类里的refresh方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 这里是根据扫描到的class生成bd的方法,跟进去看即可
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh(); // springboot依赖starter-web后,里会进入AbstractApplicationContext子类AnnotationConfigServletWebServerApplicationContext里的onRefresh(),进而启动web容器
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
。。。
上面代码里有个invokeBeanFactoryPostProcessors(beanFactory);
调用,bd的生成与管理就是在这里被执行的。
一路跟下来,会进入PostProcessorRegistrationDelegate类的下面方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)
该方法里,会调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
,这里的两个参数
· currentRegistryProcessors:是ConfigurationClassPostProcessor
· registry:是beanFactory,也就是DefaultListableBeanFactory
进入该方法,那当然就是用ConfigurationClassPostProcessor后置处理器来处理DefaultListableBeanFactory的对象beanFactory咯。
经过一次调用之后,会来到ConfigurationClassPostProcessor的public void processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法里,该方法里会拿到registry里的bdNames列表(框架提供的5个类的bd与@Configuration注解类的bd),然后遍历该列表拿到bd对象,再然后经过一些有的没的,跟我们这次核心有关,但是不需要太关注的步骤之后。就来到this.reader.loadBeanDefinitions(configClasses);
,这里·reader:是ConfigurationClassBeanDefinitionReader对象,configClasses是程序员自定义的组建类的ConfigurationClass对象列表(@Component,@Service,等注解的,包括@Configuration),自然就是要通过reader来读这些类了

那么,非框架类的Class在生成生成bd之前,会先被包装成ConfigurationClass,然后通过reader来处理(loadBeanDefinitions)。

显然,这里有多个configurationClass对象等待处理,但是因为咱们要跟踪的是通过@Bean注解的方法生成bd的过程,所以只看@Configuration注解的类,也就是AppConfig的
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
调用。好吧,大宝贝来了

这个截图我在写@Import注解是也用过,@Import与@Bean到此出的流程都一样。好了继续说@Bean

继续跟进去,会来到
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod)
方法里,这里会根据beanMethod拿到methodName,然后赋值给beanName。在搞一个ConfigurationClassBeanDefinition的对象beanDef出来。
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
再给beanDef对象设置属性,@Bean的默认几个属性
autowire, autowireCandidate, initMethod, destroyMethod, value,这几个属性都是在定义@Bean注解方法返回类里面加注解生成的。
还有resource,source属性的设置。
接下来,碎碎叨叨就注册了。
注册时的beanDef截图如下


在注册到bdMap时,beanDef里的属性如上图,重要的一些属性由箭头指出
比如MateData里的内省方法等,source,resource,factoryMethodName,factoryBeanName等等。这些属性都会影响到后面生成SpringBean的操作。
网友评论