spring加載流程之ConfigurationClassPostProcessor
-
- ConfigurationClassPostProcessor
-
- postProcessBeanDefinitionRegistry
- processConfigBeanDefinitions處理所有已經注冊的bd
- ConfigurationClassUtils
-
- checkConfigurationClassCandidate判斷bd是否帶有@Configuration等注解
- ConfigurationClassParser
-
- parse解析配置類bd
- processConfigurationClass
- doProcessConfigurationClass真正的處理
-
- 處理@PropertySource
- 處理@ComponentScan
- 處理@Import
-
- 帶有ImportSelector的類
- 帶有ImportBeanDefinitionRegistrar的類
- 普通類
- 處理@ImportResource
- 處理@Bean
- 回到ConfigurationClassPostProcessor.processConfigBeanDefinitions
-
- ConfigurationClassBeanDefinitionReade
-
- registerBeanDefinitionForImportedConfigurationClass目前配置類bd是通過@Import注入的
- oadBeanDefinitionsForBeanMethod處理配置類bd的帶有@Bean的方法
- loadBeanDefinitionsFromImportedResources處理配置類bd的@ImportResource
- loadBeanDefinitionsFromRegistrars處理配置類bd的@Import的類實作了ImportBeanDefinitionRegistrar
緣起:spring加載流程refresh之invokeBeanFactoryPostProcessors(beanFactory)
ConfigurationClassPostProcessor
postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 這裡就是根據registry(DefaultListableBeanFactory)判斷目前方法是否執行過了
// 一個工廠的後置處理器隻會執行一次
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
// 跟進
processConfigBeanDefinitions(registry);
}
跟進
processConfigBeanDefinitions(registry);
processConfigBeanDefinitions處理所有已經注冊的bd
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
/**
* registry就是DefaultListableBeanFactory
* 擷取注冊的所有beanName
*/
String[] candidateNames = registry.getBeanDefinitionNames();
/**
* 循環處理所有BeanDefinition
*/
for (String beanName : candidateNames) {
// 根據beanName獲得BeanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
/**
* 如果BeanDefinition中的configurationClass屬性為full或者lite,則意味着已經處理過了,直接跳過
*
* 後面處理BeanDefinition時,會給bd設定一個屬性(key為configurationClass,value為full或者lite)
*/
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
/**
* 判斷目前BeanDefinition是否加了@Configuration注解的類
*/
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// BeanDefinitionHolder,看成資料結構
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
/**
* 這裡的configCandidates應該隻有我們加了注解的BeanDefinition
*/
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
/**
* 如果加了@Order注解
*/
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
/**
* 由于目前傳入的是DefaultListableBeanFactory是SingletonBeanRegistry的子類
*/
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
/**
* 判斷是否有自定義的beanName生成器
*/
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
// 擷取spring預設的beanName生成器,這裡為空
if (generator != null) {
/**
* componentScanBeanNameGenerator與importBeanNameGenerator定義時就指派了new AnnotationBeanNameGenerator()
* 如果spring有預設的beanName生成器,則重新指派
*/
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
/**
* 執行個體化ConfigurationClassParser 為了解析各個配置類(帶@Configuration注解的類)
* 初始化ConfigurationClassParser的一些屬性
*/
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
/**
* 執行個體化兩個set
* candidates用于将之前加入的configCandidates去重
* alreadyParsed用于判斷是否處理過了
*/
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
/**
* 解析帶有
* @Controller
* 或@Import/@ImportResource/@ComponentScan/@ComponentScans/@Bean
* 的beanDefinition
*
* 開始掃描/注冊包下的類
*/
parser.parse(candidates);
parser.validate();
/**
* 擷取在掃描時put進去的configurationClasses
*/
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/**
* 在這裡統一處理
* 沒有注冊的進行注冊
*/
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
注意一行判斷
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory))
,判斷目前BeanDefinition是否加了@Configuration注解的類
ConfigurationClassUtils
checkConfigurationClassCandidate判斷bd是否帶有@Configuration等注解
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
/**
* 1.通過注解注入的bd都是AnnotatedGenericBeanDefinition,實作了AnnotatedBeanDefinition
* 2.spring内部的bd是RootBeanDefinition,實作了AbstractBeanDefinition
*
* 這裡判斷是不是帶有主節點額bd
*/
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
// 擷取注解
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
/**
* 判斷是否spring預設的BeanDefinition
*/
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// Check already loaded Class if present...
// since we possibly can't even load the class file for this Class.
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
metadata = new StandardAnnotationMetadata(beanClass, true);
}
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
}
return false;
}
}
/**
* 判斷目前BeanDefinition是否存在@Configuration注解
*
* 如果存在@Configuration,spring認為他是一個全注解類
*/
if (isFullConfigurationCandidate(metadata)) {
/**
* 如果存在@Configuration注解,則為目前BeanDefinition設定configurationClass屬性為full
*/
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
/**
* 判斷是否存在以下注解的bd
* candidateIndicators.add(Component.class.getName());
* candidateIndicators.add(ComponentScan.class.getName());
* candidateIndicators.add(Import.class.getName());
* candidateIndicators.add(ImportResource.class.getName());
* 或者有方法帶有@Bean的bd
*
* 如果存在spring認為他是一個部分解類
*/
else if (isLiteConfigurationCandidate(metadata)) {
/**
* 如果存在以上注解,則為目前BeanDefinition設定configurationClass屬性為lite
*/
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
ConfigurationClassParser
parse解析配置類bd
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
/**
* 根據BeanDefinition類型做不同處理
* 帶有注解的bd
*/
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
/**
* 處理需要延遲處理的ImportSelector
*/
processDeferredImportSelectors();
}
processConfigurationClass
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
/**
* 判斷是否跳過解析
*/
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
/**
* 處理Imported的情況
* 目前類有沒有被别的類@Import
*/
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);
do {
/**
* 解析各種注解
*
* 掃描指定包下的類,并注冊進DefaultListableBeanFactory
*/
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
/**
* 一個map,用來存放處理完掃描的bd
* 因為在掃描的過程中會發現bd有一些其他的注解需要處理
* 發現後會給bd設定相應的屬性值,再交由ConfigurationClassPostProcessor進行統一處理
*/
this.configurationClasses.put(configClass, configClass);
}
doProcessConfigurationClass真正的處理
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first
/**
* 處理内部類
*/
processMemberClasses(configClass, sourceClass);
// Process any @PropertySource annotations
/**
* 處理@PropertySource,處理資源檔案
*/
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
/**
* 處理@ComponentScan
*/
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
/**
* ComponentScanAnnotationParser是Spring的一個内部工具
* 它會基于某個類上的@ComponentScan注解屬性分析指定包(package)以擷取其中的bean定義
*
* 掃描普通類
* 帶有@Component等四個元注解的類
* 掃描完後注解注冊
*/
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
/**
* 一下均不是普通類:不是通過掃描出來的
* @Import/@ImportResource/@Bean等,會先放到目前ConfigurationClass中
* 然後在ConfigurationClassPostProcessor後面進行統一處理/注冊
*/
// Process any @Import annotations
/**
* @Import類型
* 1.實作ImportSelector的類
* 2.實作ImportBeanDefinitionRegistrar
* 3.普通類
*/
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations
/**
* 找到@ImportResource
* 放到目前configClass的importedResources中
* 在ConfigurationClassPostProcessor處理configClass時會随之一起處理
*/
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
/**
* 找到@Bean
* 放到目前configClass的beanMethods中
* 在ConfigurationClassPostProcessor處理configClass時會随之一起處理
*/
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
處理@PropertySource
processPropertySource(propertySource);
,具體就不看了,就是把資源檔案讀取到上下文環境中去
[email protected]的Properties資源檔案就是在這裡處理
處理@ComponentScan
例如:
@ComponentScan("com.yk.demo")
這裡可能會有多個
@ComponentScan
,因為
@ComponentScans
裡面是
ComponentScan[] value();
,用
Set
去重後循環掃描
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
// 這個ClassPathBeanDefinitionScanner在前面章節中講到過,掃描包
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
/**
* 以下都是@ComponentScan中的參數
* 有的話就取出來
*/
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
/**
* web當中講
*/
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
/**
* 預設懶加載false,此處并不是對某個bd設定lazyInit,這裡先對lazyInit設定一個值
* 在循環注冊掃描出來的bd前調用scanner.postProcessBeanDefinition方法時,會預設取這個值
*/
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
Set<String> basePackages = new LinkedHashSet<>();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
/**
* 開始執行掃描
* ComponentScanAnnotationParser 最終所使用的掃描器是ClassPathBeanDefinitionScanner
*/
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
這裡看第一行代碼
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
重新new了一個
ClassPathBeanDefinitionScanner
去做掃描
然後
scanner.doScan(StringUtils.toStringArray(basePackages))
掃描注冊部分就可以直接看我之前寫的一篇文章
spring加載流程之ClassPathBeanDefinitionScanner
處理@Import
processImports(configClass, sourceClass, getImports(sourceClass), true);
getImports(sourceClass)
擷取bd的
@Import
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
// 判斷是否重複執行了
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
// 如果是實作了ImportSelector接口的bd
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
/**
* 反射實作一個對象
* 該對象實作了ImportSelector接口
*/
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
/**
* 判斷是否DeferredImportSelector
* 延遲處理
*/
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
/**
* 執行selectImports方法
*/
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
/**
* 遞歸處理
* 被Import進來的類可能也有@Import注解
*/
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// 如果是實作了ImportBeanDefinitionRegistrar接口的bd
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
/**
* 放到目前configClass的importBeanDefinitionRegistrars中
* 在ConfigurationClassPostProcessor處理configClass時會随之一起處理
*/
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
/**
* 如果Import的類型是普通類,則将其當作帶有@Configuration的類一樣處理
* 将candidate構造為ConfigurationClass,标注為importedBy,意味着它是通過被@Import進來的
* 後面處理會用到這個判斷将這個普通類注冊進DefaultListableBeanFactory
*/
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
帶有ImportSelector的類
這裡看個實作了
ImportSelector
的例子,在配置類上添加
@Import(MySelector.class)
就可以注冊
TestSelectorService
為bd
/**
* Created by Yuk on 2019/2/2.
*/
public class MySelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{TestSelectorService.class.getName()};
}
}
/**
* Created by Yuk on 2019/2/2.
*/
public class TestSelectorService {
public void test(){
System.out.println("test selector");
}
}
更進階用法,實作一個注解,然後隻需要在配置類上添加
@EnableLuBan
就可以靈活注入
TestSelectorService
。很多
@Enable*
的自動裝配就是這樣實作的
/**
* 自動裝配
* Created by Yuk on 2019/2/2.
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MySelector.class)
public @interface EnableLuBan {
}
帶有ImportBeanDefinitionRegistrar的類
這裡還涉及到
@Import
進來的類實作了
ImportBeanDefinitionRegistrar
,但是不是在這裡處理的,這裡隻是做了一個記錄。
還是先舉個例子:
接口CardDao.java
/**
* 模拟mybatis
* 接口怎麼執行的sql語句
* 通過ImportBeanDefinitionRegistrar改變bd注冊過程,實作動态代理
* Created by Yuk on 2019/2/8.
*/
public interface CardDao {
//@Select("select * from tableName")
public void say();
}
/**
* 自定義bd注冊器
* Created by Yuk on 2019/2/8.
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
/**
* 擷取BeanDefinition
*/
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CardDao.class);
GenericBeanDefinition beanDefinition = (GenericBeanDefinition)builder.getBeanDefinition();
/**
* 改變bd的class為MyFactoryBean,具體實作交由MyFactoryBean
*/
beanDefinition.setBeanClass(MyFactoryBean.class);
/**
* 給構造函數傳參
*/
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition.getBeanClassName());
registry.registerBeanDefinition("cardDao",beanDefinition);
}
}
/**
* Created by Yuk on 2019/2/8.
*/
public class MyFactoryBean implements FactoryBean,InvocationHandler {
Class clazz;
public MyFactoryBean (Class clazz){
this.clazz = clazz;
}
@Override
public Object getObject() throws Exception {
Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class[]{clazz},
this);
return proxy;
}
@Override
public Class<?> getObjectType() {
return clazz;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("MyMapperScan. 執行sql語句");
// clazz.getAnnotation(Select.class);擷取注解的sql語句,執行
return null;
}
}
通過實作
ImportBeanDefinitionRegistrar
可以改變bd的注冊過程
實作
FactoryBean
的類注冊進
beanFactory
後,擷取bd執行的是
FactoryBean
的
getObject()
方法
實作
InvocationHandler
可以動态代理,
invoke
增強執行的方法
例子中,
CardDao
是一個接口,沒有具體實作。通過這一系列的設定,就可以通過
beanname
cardDao獲得一個FactoryBean的代理類,執行
say()
就會執行
invoke
方法
CardDao->MyFactoryBean->getObject()->proxy
普通類
/**
* 如果Import的類型是普通類,則将其當作帶有@Configuration的類一樣處理
* 将candidate構造為ConfigurationClass,标注為importedBy,意味着它是通過被@Import進來的
* 後面處理會用到這個判斷将這個普通類注冊進DefaultListableBeanFactory
*/
processConfigurationClass(candidate.asConfigClass(configClass));
處理@ImportResource
這裡不做過多解釋,就是對
locations
參數做處理,它是一個數組,然後先記錄到目前
configClass
中
處理@Bean
就是看目前
configClass
是否有@Bean的方法,也是記錄下來
回到ConfigurationClassPostProcessor.processConfigBeanDefinitions
掃描完回到
ConfigurationClassPostProcessor
的
processConfigBeanDefinitions
方法
/**
* 擷取在掃描時put進去的configurationClasses
*/
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
這裡的parser.getConfigurationClasses(),就是在ConfigurationClassParser中
/**
* 一個map,用來存放處理完掃描的bd
* 因為在掃描的過程中會發現bd有一些其他的注解需要處理
* 發現後會給bd設定相應的屬性值,再交由ConfigurationClassPostProcessor進行統一處理
*/
this.configurationClasses.put(configClass, configClass);
繼續執行processConfigBeanDefinitions
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/**
* 在這裡統一處理
* 處理其實作ImportBeanDefinitionRegistrar的bd
* 處理注解@ImportResource和@Bean
*/
this.reader.loadBeanDefinitions(configClasses);
ConfigurationClassBeanDefinitionReade
注冊bd,處理兩For兩From
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
registerBeanDefinitionForImportedConfigurationClass目前配置類bd是通過@Import注入的
/**
* 目前類是通過@Import注入的
*/
if (configClass.isImported()) {
/**
* 注冊進DefaultListableBeanFactory
*/
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
oadBeanDefinitionsForBeanMethod處理配置類bd的帶有@Bean的方法
/**
* 處理/注冊@Bean注解
*/
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources處理配置類bd的@ImportResource
/**
* 處理通過@ImportResource進來的xml檔案(spring的配置檔案)
*/
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars處理配置類bd的@Import的類實作了ImportBeanDefinitionRegistrar
/**
* 處理通過自定義實作ImportBeanDefinitionRegistrar的類注冊的bean
*/
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());