網(wǎng)站建設(shè)外包流程網(wǎng)站排名優(yōu)化怎樣做
文章目錄
- 一、源碼時序圖
- 1. 注冊ConfigurationClassPostProcessor流程源碼時序圖
- 2. 注冊ConfigurationAnnotationConfig流程源碼時序圖
- 3. 實例化流程源碼時序圖
- 二、源碼解析
- 1. 注冊ConfigurationClassPostProcessor流程源碼解析
- (1)運行案例程序啟動類ConfigurationAnnotationTest的main()方法
- (2)解析AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>... componentClasses)構(gòu)造方法
- (3)解析AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext()無參構(gòu)造方法
- (4)解析AnnotatedBeanDefinitionReader類中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)構(gòu)造方法
- (5)解析AnnotatedBeanDefinitionReader類的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)構(gòu)造方法
- (6)解析AnnotationConfigUtils類的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法
- (7)解析AnnotationConfigUtils類的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)方法
- (8)解析registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)方法
- (9)解析DefaultListableBeanFactory類的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法
- 2. 注冊ConfigurationAnnotationConfig流程源碼解析
- (1)運行案例程序啟動類ConfigurationAnnotationTest的main()方法,并進入AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>... componentClasses)構(gòu)造方法。
- (2)解析AnnotationConfigApplicationContext類的register(Class<?>... componentClasses)方法
- (3)解析AnnotatedBeanDefinitionReader類的register(Class<?>... componentClasses)方法
- (4)解析AnnotatedBeanDefinitionReader類的registerBean(Class<?> beanClass)方法
- (5)解析AnnotatedBeanDefinitionReader類的doRegisterBean(ClassbeanClass, String name, Class<? extends Annotation>[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法。
- (6)解析BeanDefinitionReaderUtils類的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法
- 3. 實例化流程源碼解析
- (1)運行案例程序啟動類ConfigurationAnnotationTest的main()方法,并進入AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>... componentClasses)構(gòu)造方法。
- (2)解析AbstractApplicationContext類的refresh()方法
- (3)解析AbstractApplicationContext類的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法
- (4)解析PostProcessorRegistrationDelegate類的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法
- (5)解析PostProcessorRegistrationDelegate類的invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory)方法
- (6)解析ConfigurationClassPostProcessor類中的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法
- (7)解析ConfigurationClassPostProcessor類的enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法
- (8)解析ConfigurationClassEnhancer類的enhance(Class<?> configClass, ClassLoader classLoader)方法
- (9)解析ConfigurationClassEnhancer類的newEnhancer(Class<?> configSuperClass, ClassLoader classLoader)方法
- (10)解析ConfigurationClassEnhancer類的createClass(Enhancer enhancer)方法
- (11)解析CALLBACKS
- (12)解析BeanMethodInterceptor類
- (13)解析BeanMethodInterceptor類的resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName)方法
- 三、總結(jié)
一、源碼時序圖
就@Configuration注解本身而言,在源碼層面的執(zhí)行流程涉及到注冊與實例化兩種執(zhí)行流程。
就注冊流程而言,會涉及到Spring內(nèi)部的ConfigurationClassPostProcessor類的Bean定義信息的注冊流程,以及上一篇文章案例中(鏈接)標(biāo)注了@Configuration注解的ConfigurationAnnotationConfig配置類的Bean定義信息注冊流程。
注意:本章的源碼時序圖和源碼解析均以上一章案例程序(鏈接)作為入口進行分析,并且會在ConfigurationAnnotationConfig類上標(biāo)注@Configuration注解,同時在ConfigurationAnnotationTest測試類中,調(diào)用AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>… componentClasses)構(gòu)造方法來創(chuàng)建IOC容器。
1. 注冊ConfigurationClassPostProcessor流程源碼時序圖
ConfigurationClassPostProcessor后置處理器是解析@Configuration注解的核心類,也是Spring中的一個非常重要的后置處理器類, Spring IOC容器啟動時,會向IOC容器中注冊ConfigurationClassPostProcessor類的Bean定義信息。向IOC容器中注冊ConfigurationClassPostProcessor類的Bean定義信息的時序圖如圖所示。
由圖可以看出,Spring IOC容器啟動時,向IOC容器中注冊ConfigurationClassPostProcessor類的Bean定義信息時,會涉及到AnnotationConfigApplicationContext類、AnnotatedBeanDefinitionReader類和AnnotationConfigUtils類中方法的調(diào)用。具體源碼的調(diào)用細(xì)節(jié)見源碼解析部分。
2. 注冊ConfigurationAnnotationConfig流程源碼時序圖
ConfigurationAnnotationConfig類是本章中案例程序的配置類,在ConfigurationAnnotationConfig類上標(biāo)注了@Configuration注解,當(dāng)Spring IOC容器啟動時,也會將ConfigurationAnnotationConfig類的Bean定義信息注冊到Spring IOC容器中,向Spring IOC容器中注冊ConfigurationAnnotationConfig類的Bean定義信息的時序圖如圖所示。
由圖可以看出,Spring IOC容器啟動時,向IOC容器中注冊ConfigurationAnnotationConfig類的Bean定義信息時,會涉及到AnnotationConfigApplicationContext類、AnnotatedBeanDefinitionReader類、BeanDefinitionReaderUtils類和DefaultListableBeanFactory類的方法調(diào)用,具體的源碼調(diào)用細(xì)節(jié)見源碼解析部分。
注意:Spring IOC容器在啟動時,會向IOC容器中注冊ConfigurationClassPostProcessor類的bean定義信息和使用@Configuration注解標(biāo)注的ConfigurationAnnotationConfig配置類的Bean定義信息。當(dāng)Spring IOC容器在刷新時,會遞歸處理所有使用@Configuration注解標(biāo)注的類,解析@Bean等注解標(biāo)注的方法,解析成一個個ConfigurationClassBeanDefinition類型的BeanDefinition對象,注冊到IOC容器中。Spring IOC容器刷新時,解析@Bean等注解的時序圖和源碼執(zhí)行流程會在后續(xù)章節(jié)介紹@Bean等注解時詳細(xì)介紹,這里不再贅述。
3. 實例化流程源碼時序圖
Spring IOC容器在啟動過程中,最終會調(diào)用AnnotationConfigApplicationContext類的refresh()方法刷新IOC容器,刷新IOC容器的過程中就會對標(biāo)注了@Configuration注解的配置類進行實例化。本節(jié),就結(jié)合案例程序簡單分析下刷新IOC容器時,對標(biāo)注了@Configuration注解的配置類進行實例化的源碼時序圖,源碼時序圖如圖所示。
由圖可以看出,刷新IOC容器時,對標(biāo)注了@Configuration注解的配置類進行實例化時,會涉及到AnnotationConfigApplicationContext類、AbstractApplicationContext類、PostProcessorRegistrationDelegate類、ConfigurationClassPostProcessor類和ConfigurationClassEnhancer類方法的調(diào)用,具體方法調(diào)用的細(xì)節(jié)見源碼解析部分。
二、源碼解析
本節(jié),同樣按照注冊流程和實例化流程來深入分析@Configuration注解在Spring源碼層面的執(zhí)行流程。
1. 注冊ConfigurationClassPostProcessor流程源碼解析
@Configuration注解涉及到ConfigurationClassPostProcessor類的Bean定義信息的注冊流程的源碼執(zhí)行過程可結(jié)合圖1-1進行分析。啟動Spring IOC容器時,@Configuration注解涉及到的ConfigurationClassPostProcessor核心類的注冊流程的源碼執(zhí)行過程如下所示。
(1)運行案例程序啟動類ConfigurationAnnotationTest的main()方法
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class);//#############省略其他代碼##################
}
可以看到,在main()方法中會調(diào)用AnnotationConfigApplicationContext類的構(gòu)造方法傳入配置類ConfigurationAnnotationConfig的Class對象來創(chuàng)建IOC容器。接下來,會進入AnnotationConfigApplicationContext類的構(gòu)造方法。
(2)解析AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>… componentClasses)構(gòu)造方法
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {this();register(componentClasses);refresh();
}
可以看到,在上述構(gòu)造方法中,會通過this()調(diào)用AnnotationConfigApplicationContext類的無參構(gòu)造方法。
(3)解析AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext()無參構(gòu)造方法
public AnnotationConfigApplicationContext() {StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");this.reader = new AnnotatedBeanDefinitionReader(this);createAnnotatedBeanDefReader.end();this.scanner = new ClassPathBeanDefinitionScanner(this);
}
可以看到,在AnnotationConfigApplicationContext類的無參構(gòu)造方法中,主要的邏輯就是實例化了AnnotatedBeanDefinitionReader類型的reader成員變量和ClassPathBeanDefinitionScanner類型的scanner成員變量。
- reader:表示注解類型的Bean定義信息讀取器,主要就是讀取通過注解方式進行實例化的Bean的定義信息。
- scanner:表示類路徑下的Bean定義掃描器,主要就是掃描類路徑下的Bean定義信息。
@Configuration注解涉及到的注冊流程源碼的執(zhí)行過程,會執(zhí)行實例化reader成員變量的代碼,也就是下面的代碼片段。
this.reader = new AnnotatedBeanDefinitionReader(this);
接下來,會調(diào)用AnnotatedBeanDefinitionReader類中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)構(gòu)造方法。
(4)解析AnnotatedBeanDefinitionReader類中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)構(gòu)造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));
}
可以看到,在上述構(gòu)造方法中,通過this調(diào)用了AnnotatedBeanDefinitionReader類的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)構(gòu)造方法。
(5)解析AnnotatedBeanDefinitionReader類的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)構(gòu)造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");this.registry = registry;this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
可以看到,在上述構(gòu)造方法中,最核心的邏輯就是調(diào)用了AnnotationConfigUtils工具類的registerAnnotationConfigProcessors()方法,將BeanDefinitionRegistry類型的registry對象傳入方法中。其中,registry對象本質(zhì)上就是一個AnnotationConfigApplicationContext類對象的實例,這是因為AnnotationConfigApplicationContext類繼承了GenericApplicationContext類,而GenericApplicationContext類實現(xiàn)了BeanDefinitionRegistry接口。
(6)解析AnnotationConfigUtils類的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);
}
可以看到,在AnnotationConfigUtils類的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法中調(diào)用了AnnotationConfigUtils類中的另外一個registerAnnotationConfigProcessors()方法。
(7)解析AnnotationConfigUtils類的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)方法
這里,只給出在AnnotationConfigUtils類的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)方法中,將@Configuration注解涉及到的ConfigurationClassPostProcessor類的Bean定義信息注冊到IOC容器中的核心代碼,如下所示。
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME ="org.springframework.context.annotation.internalConfigurationAnnotationProcessor";public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {//################省略其他代碼########################if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}//################省略其他代碼########################
}
可以看到,會調(diào)用registerPostProcessor()方法注冊后置處理器。
(8)解析registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)方法
private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(beanName, definition);return new BeanDefinitionHolder(definition, beanName);
}
可以看到,上述代碼中,調(diào)用了registry參數(shù)的registerBeanDefinition()方法來注冊ConfigurationClassPostProcessor類的Bean定義信息,definition參數(shù)本質(zhì)上就是一個AnnotationConfigApplicationContext類的實例對象。最終會調(diào)用DefaultListableBeanFactory類的registerBeanDefinition()方法來注冊ConfigurationClassPostProcessor類的Bean定義信息。
(9)解析DefaultListableBeanFactory類的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {//##################省略其他代碼###############this.beanDefinitionMap.put(beanName, beanDefinition);//##################省略其他代碼###############
}
通過上述代碼可知,向Spring的IOC容器中注冊類的Bean定義信息,其實就是向beanDefinitionMap對象中添加元素,beanDefinitionMap對象本質(zhì)上是一個ConcurrentHashMap對象。向beanDefinitionMap對象中添加的元素的Key為Bean的名稱,Value為Bean的定義信息。
beanDefinitionMap源碼詳見:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
至此,@Configuration注解涉及到的ConfigurationClassPostProcessor類的注冊過程分析完畢。
2. 注冊ConfigurationAnnotationConfig流程源碼解析
使用@Configuration注解標(biāo)注的ConfigurationAnnotationConfig類的Bean定義信息的注冊流程的源碼執(zhí)行過程可結(jié)合之前的時序圖進行分析,啟動Spring IOC容器時,向IOC容器中注冊ConfigurationAnnotationConfig類的Bean定義信息的源碼執(zhí)行過程如下所示。
(1)運行案例程序啟動類ConfigurationAnnotationTest的main()方法,并進入AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>… componentClasses)構(gòu)造方法。
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {this();register(componentClasses);refresh();
}
可以看到,在AnnotationConfigApplicationContext(Class<?>… componentClasses)方法中調(diào)用了register()方法,傳入componentClasses參數(shù)進行注冊。
(2)解析AnnotationConfigApplicationContext類的register(Class<?>… componentClasses)方法
@Override
public void register(Class<?>... componentClasses) {//###########省略其他代碼##############this.reader.register(componentClasses);//###########省略其他代碼##############
}
可以看到,在register(Class<?>… componentClasses)方法中調(diào)用了reader的register()方法。
(3)解析AnnotatedBeanDefinitionReader類的register(Class<?>… componentClasses)方法
public void register(Class<?>... componentClasses) {for (Class<?> componentClass : componentClasses) {registerBean(componentClass);}
}
可以看到,在register(Class<?>… componentClasses)方法中,會循環(huán)遍歷傳入的可變參數(shù)componentClasses,每次循環(huán)時,都會調(diào)用registerBean()方法。
(4)解析AnnotatedBeanDefinitionReader類的registerBean(Class<?> beanClass)方法
public void registerBean(Class<?> beanClass) {doRegisterBean(beanClass, null, null, null, null);
}
可以看到,在registerBean(Class<?> beanClass)方法中調(diào)用了doRegisterBean()方法。
(5)解析AnnotatedBeanDefinitionReader類的doRegisterBean(ClassbeanClass, String name, Class<? extends Annotation>[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法。
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);//###########################省略其他代碼#############################String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));//###########################省略其他代碼#############################BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
可以看到,在doRegisterBean(ClassbeanClass, String name, Class<? extends Annotation>[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法中調(diào)用了BeanDefinitionReaderUtils類的registerBeanDefinition()方法。
(6)解析BeanDefinitionReaderUtils類的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());//###########################省略其他代碼#############################
}
可以看到,在registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法中通過調(diào)用registry的registerBeanDefinition()方法來向IOC容器中注冊Bean定義信息。
注意:到目前為止,后續(xù)向IOC容器注冊Bean定義信息的源碼執(zhí)行流程與向IOC容器中注冊ConfigurationClassPostProcessor類的Bean定義信息的源碼執(zhí)行流程基本相同,這里不再贅述。
3. 實例化流程源碼解析
Spring IOC容器在刷新時,會實例化使用@Configuration注解標(biāo)注的類,可結(jié)合之前的時序圖理解,具體的源碼執(zhí)行流程如下所示。
(1)運行案例程序啟動類ConfigurationAnnotationTest的main()方法,并進入AnnotationConfigApplicationContext類的AnnotationConfigApplicationContext(Class<?>… componentClasses)構(gòu)造方法。
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {this();register(componentClasses);refresh();
}
可以看到,在AnnotationConfigApplicationContext(Class<?>… componentClasses)構(gòu)造方法中會調(diào)用refresh()方法刷新IOC容器。
(2)解析AbstractApplicationContext類的refresh()方法
@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//#############省略其他代碼#####################try {//#############省略其他代碼#####################invokeBeanFactoryPostProcessors(beanFactory);//#############省略其他代碼#####################}catch (BeansException ex) {//#############省略其他代碼#####################}finally {//#############省略其他代碼#####################}}
}
可以看到,在refresh()方法中調(diào)用了invokeBeanFactoryPostProcessors()方法。
(3)解析AbstractApplicationContext類的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());//################省略其他代碼####################
}
可以看到,在invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法中調(diào)用了PostProcessorRegistrationDelegate類的invokeBeanFactoryPostProcessors()方法。
(4)解析PostProcessorRegistrationDelegate類的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {//#################省略其他代碼##################invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);//#################省略其他代碼##################
}
在invokeBeanFactoryPostProcessors()方法中會解析標(biāo)注了@Configuration注解的類中標(biāo)注了@Bean等注解的方法,生成相應(yīng)的Bean定義信息注冊到IOC容器中。這里,主要關(guān)注的是標(biāo)注了@Configuration注解的類的實例化過程,所以,只需要關(guān)注invokeBeanFactoryPostProcessors()方法中的上述代碼片段即可。
可以看到,在invokeBeanFactoryPostProcessors()方法中又調(diào)用了PostProcessorRegistrationDelegate類中的另一個invokeBeanFactoryPostProcessors()方法。
(5)解析PostProcessorRegistrationDelegate類的invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory)方法
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process").tag("postProcessor", postProcessor::toString);postProcessor.postProcessBeanFactory(beanFactory);postProcessBeanFactory.end();}
}
可以看到,在invokeBeanFactoryPostProcessors()方法中,會循環(huán)遍歷傳遞進來的所有postProcessors集合,每次循環(huán)時,都會使用一個postProcessor對象來接收postProcessors集合中的每一個元素,調(diào)用postProcessor對象的postProcessBeanFactory()方法,并傳入beanFactory來實例化對象。
(6)解析ConfigurationClassPostProcessor類中的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {//##############省略其他代碼###############enhanceConfigurationClasses(beanFactory);beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
可以看到,在postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法中調(diào)用了enhanceConfigurationClasses()方法。
(7)解析ConfigurationClassPostProcessor類的enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {//################省略其他代碼########################ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {AbstractBeanDefinition beanDef = entry.getValue();// If a @Configuration class gets proxied, always proxy the target classbeanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// Set enhanced subclass of the user-specified bean classClass<?> configClass = beanDef.getBeanClass();Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);if (configClass != enhancedClass) {//################省略其他代碼###################beanDef.setBeanClass(enhancedClass);}}enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
}
可以看到,在enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法中,主要是使用ConfigurationClassEnhancer對象的enhance()方法生成代理類,也就是使用CGLib生成代理類。
(8)解析ConfigurationClassEnhancer類的enhance(Class<?> configClass, ClassLoader classLoader)方法
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {//###################省略其他代碼###############Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));//###################省略其他代碼###############return enhancedClass;
}
可以看到,在enhance(Class<?> configClass, ClassLoader classLoader)方法中調(diào)用了createClass()方法創(chuàng)建代理類,在這之前先調(diào)用newEnhancer()方法實例化Enhancer對象。
(9)解析ConfigurationClassEnhancer類的newEnhancer(Class<?> configSuperClass, ClassLoader classLoader)方法
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(configSuperClass);enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});enhancer.setUseFactory(false);enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setAttemptLoad(true);enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));enhancer.setCallbackFilter(CALLBACK_FILTER);enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());return enhancer;
}
可以看到,newEnhancer()方法中主要是生成CGLib動態(tài)代理的Enhancer對象,后續(xù)會使用Enhancer對象生成代理類。
在newEnhancer()方法中為要生成的代理類設(shè)置了父類和接口,由于為要生成的代理類設(shè)置的接口為EnhancedConfiguration,同時,EnhancedConfiguration接口繼承了BeanFactoryAware接口,所以,在后續(xù)生成的代理類中可以調(diào)用BeanFactoryAware接口的setBeanFactory(BeanFactory beanFactory)方法獲取到beanFactory對象。
(10)解析ConfigurationClassEnhancer類的createClass(Enhancer enhancer)方法
private Class<?> createClass(Enhancer enhancer) {Class<?> subclass = enhancer.createClass();Enhancer.registerStaticCallbacks(subclass, CALLBACKS);return subclass;
}
可以看到,在createClass(Enhancer enhancer)方法中,主要調(diào)用了enhancer對象的createClass()方法來創(chuàng)建代理類,因為使用CGLib創(chuàng)建出來的代理類是目標(biāo)類的子類,所以,這里創(chuàng)建出來的代理類就是目標(biāo)類的子類。
(11)解析CALLBACKS
最后,再來關(guān)注下Enhancer類中傳入的CALLBACKS參數(shù)。
static final Callback[] CALLBACKS = new Callback[] {new BeanMethodInterceptor(),new BeanFactoryAwareMethodInterceptor(),NoOp.INSTANCE
};
可以看到,CALLBACKS是一個Callback類型的數(shù)組,數(shù)組中的每個元素都是一個Callback類型的對象。其中,BeanMethodInterceptor類和BeanFactoryAwareMethodInterceptor類也是攔截器類型。接下來,以BeanMethodInterceptor類為例進行介紹。
(12)解析BeanMethodInterceptor類
BeanMethodInterceptor實現(xiàn)了MethodInterceptor接口和ConditionalCallback接口,主要的作用就是對標(biāo)注了@Bean的注解的方法進行攔截,執(zhí)行intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs, MethodProxy cglibMethodProxy)方法,生成Bean的實例對象。在方法中有如下一段代碼邏輯。
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,MethodProxy cglibMethodProxy) throws Throwable {// 如果已經(jīng)創(chuàng)建了Bean的代理實例對象,則調(diào)用父類的方法。if (isCurrentlyInvokedFactoryMethod(beanMethod)) {//#################省略其他代碼###############return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);}return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
上述代碼能夠保證在類上添加@Configuration注解后,只會為類生成一個代理對象。也就是說,上述代碼的邏輯能夠保證標(biāo)注了@Configuration注解的類生成的代理類是單例模式的。
因為使用CGLib創(chuàng)建出來的代理類是目標(biāo)類的子類,所以第一次執(zhí)行上述代碼片段時,會調(diào)用cglibMethodProxy的invokeSuper()方法執(zhí)行父類的方法,也就是執(zhí)行目標(biāo)類的方法。第二次執(zhí)行上述代碼片段時,會調(diào)用resolveBeanReference()方法。
(13)解析BeanMethodInterceptor類的resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName)方法
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName) {//##############省略其他代碼###############boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);try {//##############省略其他代碼###############Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :beanFactory.getBean(beanName));//##############省略其他代碼###############return beanInstance;}finally {//##############省略其他代碼###############}
}
可以看到,從resolveBeanReference()方法中,會通過beanFactory獲取已經(jīng)初始化好的Bean對象,并將這個已經(jīng)初始化好的bean對象返回。并不會再進行第二次初始化的操作。
所以,在類上添加@Configuration注解后,Spring能夠保證為類生成的代理類是單例的。
三、總結(jié)
上一章和本章,主要對@Configuration注解進行了系統(tǒng)性的介紹。首先,對@Configuration注解進行了簡單的說明,包括@Configuration注解的源碼和使用場景以及注意事項。隨后,給出了@Configuration注解的使用案例,本章的案例主要是針對使用@Configuration注解的一些注意事項給出的案例。接下來,詳細(xì)介紹了@Configuration注解在Spring源碼層面執(zhí)行的時序圖和對應(yīng)的源碼流程。其中,對于注冊流程,主要介紹了注冊ConfigurationClassPostProcessor類后置處理器的Bean定義信息和ConfigurationAnnotationConfig配置類Bean定義信息的注冊時序圖和源碼執(zhí)行流程。對于實例化流程,主要介紹了在Spring IOC容器刷新時,實例化ConfigurationAnnotationConfig配置類的代理對象的流程。