spring加载流程之ConfigurationClassPostProcessor
缘起: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);
,具体就不看了,就是把资源文件读取到上下文环境中去
1.@PropertySource的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());