spring配置文件
spring配置文件
相关类
@Configuration
:标注在类上,表示该类是个Full模式的配置类。自Spring 5.2.0版本后它加了个proxyBeanMethods
属性来显示控制Full模式还是Lite模式,默认是true表示Full模式。@Bean
:标注在方法上,表示方法生成一个由Spring容器管理的Bean。ConfigurationClassPostProcessor
:用于引导处理@Configuration配置类的后置处理器。注意:它只是引导处理,并不是实际处理。ConfigurationClassUtils
:内部工具类。用于判断组件是否是配置类,又或是Full模式/Lite模式,然后在bd元数据里打上标记。它还会处理一件小事:获取@Configuration配置类上标注的@Order排序值并放进bd里。BeanMethod
:内部使用的类。用于封装标注有@Bean注解的方法。ConfigurationClass
:内部使用的类。每一个@Configuration配置类都会被封装为它,内部会包含多个@Bean方法(BeanMethod)。ConfigurationClassParser
:解析@Configuration配置类,最终以ConfigurationClass对象的形式展示,并且填充它:因为一个配置类可以@Import
导入另外一个(或者N多个)其它配置类,所以需要填充。ConfigurationClassBeanDefinitionReader
:内部使用的类。读取给定的已经解析好的Set<ConfigurationClass>
集合,把里面的bd信息注册到BeanDefinitionRegistry
里去(这里决定了bd的有序和无序相关问题)。ConfigurationClassEnhancer
:内部使用的类。配置类增强器,用于对@Configuration类(Full模式)使用CGLIB增强,生成一个代理子类字节码Class对象。EnhancedConfiguration
:被增强器增强过的配置类,都会自动的让实现此接口(实际是个BeanFactoryAware
)接口。SpringNamingPolicy
:使用CGLIB生成字节码类名名称生成策略 -> 名称中会有BySpringCGLIB
字样。BeanFactoryAwareMethodInterceptor
:CGLIB代理对象拦截器。作用:拦截代理类的setBeanFactory()
方法,给对应属性赋值。BeanMethodInterceptor
:CGLIB代理对象拦截器。作用:拦截所有@Bean方法的执行,以支持可以通过直接调用@Bean方法来管理依赖关系(当然也支持FactoryBean
模式)。
ConfigurationClassPostProcessor
配置类解析流程
配置类的解析均是交由ConfigurationClassPostProcessor
来引导。在Spring Framework里(非Spring Boot)里,它是BeanDefinitionRegistryPostProcessor
处理器的唯一实现类,用于引导处理@Configuration
配置类。解析入口是postProcessBeanDefinitionRegistry()
方法,实际处理委托给了processConfigBeanDefinitions()
方法。
ConfigurationClassPostProcessor
从注册进来的配置类(可能是Full模式,可能是Lite模式)里进一步派生bean定义。简而言之:收集到所有的BeanDefinition
(后简称为bd)存储起来,包括@Import、@Component
等等组件。并且做出标注:是Full模式的还是Lite模式的配置类(若非配置组件就不标注)。
ConfigurationClassPostProcessor:
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 生成一个id,放置后面再重复执行
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);
}
// 表示此registry里的bd收集动作,已经做了 避免再重复收集此registry
this.registriesPostProcessed.add(registryId);
// 根据配置类,收集到所有的bd信息 并且做出mark标注:是Full模式还是Lite模式,很重要
processConfigBeanDefinitions(registry);
}
/**
* 根据配置类,收集到所有的bd信息 并且做出mark标注:是Full模式还是Lite模式,很重要
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
/**
* 1. 启动时传入的配置类会注册到容器中 {@link AnnotationConfigApplicationContext#register(Class[])}
* 2. BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor 里面注册 {@link AbstractApplicationContext#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory)}
* */
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
// Bean 定义已作为配置类进行处理
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
/**
* 判断是否是配置类
* 有 @Configuration(proxyBeanMethods=true) full配置类
* 有 @Configuration(proxyBeanMethods=false) lite配置类
* 无 @Configuration 但是有 (@Component || @ComponentScan || @Import || @ImportResource || @Bean ) lite配置类
*
* 是配置类,还会解析 @Order 注解的值,设置到 BeanDefinition 中。目的是后面配置类排序
* */
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//如果未找到@Configuration类,请立即返回
if (configCandidates.isEmpty()) {
return;
}
/**
* 通过 Order可以排序,升序排序, order越小越靠前。
* 可以在配置类上标注 @Order,调整配置类的解析顺序。
* 升序排列。
* */
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
//检测通过封闭的应用程序上下文提供的任何自定义 Bean 名称生成策略
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
// 可以预先往单例池中添加一个 CONFIGURATION_BEAN_NAME_ GENERATOR的 BeanNameGenerator类型的bean
// 可以用来作为扫描得到的Bean和 import导入进来的Bean的 beanName
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 解析每个@Configuration类
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
/**
* 解析配置类,会把每个 BeanDefinitionHolder 解析为 ConfigurationClass
* 会解析 @Bean、@Component、@ComponentScan、@ComponentScans、@Import、@ImportResource 也就是会解析出配置类里面的配置类。递归解析
*
* 解析完 configClasses,结果是:
* 1. @Bean 标注的方法, --> beanMethods属性
* 2. @ImportResource --> importedResources属性
* 3. @Import(ImportBeanDefinitionRegistrar.class) --> importBeanDefinitionRegistrars属性,后面会回调方法
* 4. @Import(ImportSelector.class) --> 执行 ImportSelector#selectImports,返回值都解析成配置类
* 5. @Import() --> 解析成configClass
* 6. @Import(DeferredImportSelector.class) --> deferredImportSelectorHandler
*
* 注:
* 1. 使用 @Import 导入的类一定是配置类
* 2. @Import(DeferredImportSelector.class) 会延时解析,SpringBoot 的自动转配 就是通过这个机制实现的。通过延时解析保证 @ConditionalOnXx 注解能正确判断
*/
parser.parse(candidates); // AppConfig.class ---> BeanDefinition
parser.validate();
// configClasses 相当于就是解析之后的结果
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());
}
/**
* 【@Bean 第三步】因为解析完的 configClasses 里面会记录 @Bean标注的方法,这个方法被称为 factoryMethod
* 会在下面的方法注册成 beanDefinition
*/
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size()))
.end();
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());
/**
* 注册 记录了@Import(A.class)的信息到BeanFactory中,在这里会用到
* {@link ImportAwareBeanPostProcessor#postProcessBeforeInitialization(Object, String)}
* */
// 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();
}
}
ConfigurationClassUtils
ConfigurationClassUtils:
/**
* 检查给定的 bean 定义是否是配置类的候选者
* (或在配置/组件类中声明的嵌套组件类,
* 也要自动注册),并相应地标记它。
* @param beanDef 要检查的 bean 定义
* @param metadataReaderFactory 调用方当前使用的工厂
* @return 候选人是否有资格成为(任何类型的)配置类
*/
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
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();
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
BeanPostProcessor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {
return false;
}
metadata = AnnotationMetadata.introspect(beanClass);
}
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;
}
}
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
// full 配置类
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
// 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
ConfigurationClassParser:
/**
* 配置类解析
*/
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
/**
* 加载完所有的配置类里面的信息。
* 这里会解析的内容是:
* 1. @Component
* 1.1 获取所有的成员内部类 {@link ConfigurationClassParser#processMemberClasses(ConfigurationClass, SourceClass, Predicate)}
* 1.2 判断是否是配置类 {@link ConfigurationClassUtils#isConfigurationCandidate(AnnotationMetadata)}
* 1.3 递归解析 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
*
* 2. @PropertySources
*
* 3. @ComponentScans、@ComponentScan
* 3.1 扫描指定包的内容,并注册到IOC容器中 {@link ComponentScanAnnotationParser#parse(AnnotationAttributes, String)}
* 3.2 判断是否是配置类 {@link ConfigurationClassUtils#checkConfigurationClassCandidate(BeanDefinition, MetadataReaderFactory)}
* 3.3 是配置类,就解析配置类 {@link ConfigurationClassParser#parse(String, String)}
*
* 4. @Import(非DeferredImportSelector的类) --> 递归调用 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
* 处理 @Import(selector.class),最终的结果都是按照配置类来解析 {@link ConfigurationClassParser#processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}
* 4.1 selector instanceof DeferredImportSelector 。先存起来,这种类型需要延时解析 {@link DeferredImportSelectorHandler#handle(ConfigurationClass, DeferredImportSelector)}
* 4.2 selector instanceof ImportSelector。递归解析Import {@link ConfigurationClassParser#processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}
* 4.3 select instanceof ImportBeanDefinitionRegistrar。设置为 configClass 的属性 {@link ConfigurationClass#addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar, AnnotationMetadata)}
* 4.4 兜底方法,这个就是关键,通过这就能看出 所有@Import导入的类,都会被解析成配置类 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
*
* 可以发现 @Import(DeferredImportSelector.class) 没有立即解析,而是先存起来 带所有配置类解析完之后。在遍历 回调接口方法,递归执行 {@link ConfigurationClassParser#processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}
* 虽然 @Import(ImportBeanDefinitionRegistrar.class) 也是存起来,但是他是作为 configClass的属性,后面注册BeanDefinition的时候,直接回调方法。不像
* @Import(DeferredImportSelector.class) 还会解析回调的结果
*
* 6. @ImportResource
* 设置为 configClass 的属性 {@link ConfigurationClass#addImportedResource(String, Class)}
*
* 7. @Bean
* 设置为 configClass 的属性 {@link ConfigurationClass#addBeanMethod(BeanMethod)}
*
* 8. 有父类,且父类含有@Bean方法
* 8.1 knownSuperclasses.put(superclass, configClass); 记录父类被加载了,避免多个子类是配置类的情况 其父类配置类会被解析多次的问题
* 8.2 返回父类
* 8.2 因为是 do...while 执行 {@link ConfigurationClassParser#doProcessConfigurationClass(ConfigurationClass, SourceClass, Predicate)}
* 所以实现了递归解析配置类的父类
* 8.3 最终解析的 @Bean 会添加到子类配置类的属性中。比如:
* @Configuration
* class A extends C {}
* @Configuration
* class B extends C {}
* class C {
* @Bean
* public A bean(){
* return new A();
* }
* }
*
* 假设 A 比 B 先解析,也就是执行 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
* 那么 bean 是属于 A配置类的,不是属于B配置类的
*
* */
BeanDefinition bd = holder.getBeanDefinition();
try {
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);
}
}
/**
* 开始解析 @Import(DeferredImportSelector 的实现类)
* SpringBoot 的自动装配就是通过实现这个接口实现的,目的就是延时加载。因为很多 AutoConfigurationClass 会使用 @ConditionOnMissXx 来判断是否注入bean
* 所以需要延时加载,才能正确的判断
* */
this.deferredImportSelectorHandler.process();
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
// 根据 @Conditional 确定是否应跳过。
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
// 该配置类是通过@{@link Import}注册的,或者是由于嵌套在另一个配置类中而自动注册的(比如扫描到的成员内部类是配置类的情况)
if (configClass.isImported()) {
// 该配置类是通过@{@link Import}注册的,或者是由于嵌套在另一个配置类中而自动注册的(比如扫描到的成员内部类是配置类的情况)
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// 否则忽略新导入的配置类;现有的非导入类将覆盖它。
return;
} else {
// 找到显式 Bean 定义,可能替换了导入。让我们删除旧的,然后使用新的。
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values()
.removeIf(configClass::equals);
}
}
// 递归处理配置类及其超类层次结构。
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
} while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
/**
* @param configClass 正在构建的配置类
* @param sourceClass 一个源类
* @return 超类,如果未找到或之前未处理,则为 {@code null}
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
// 配置类有 @Component
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 处理内部类 是否有配置类
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter);
}
// 就是拿到 @PropertySources、@PropertySource 注解
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
/**
* 就是将注解对应的资源文件 构造成 PropertySource 类型的对象,并将对象存到 {@link AbstractEnvironment#propertySources} 属性中。
*
* 使用 `context.getEnvironment().getProperty("name")` 就能读到 资源文件 中定义的内容了
* */
processPropertySource(propertySource);
} else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata()
.getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 会进行扫描,得到的 BeanDefinition会注册到 Spring容器中,并且会检查是不是配置类并进行解析
// Process any @ComponentScan annotations
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) {
// 这里就会进行扫描,得到的 BeanDefinition会注册到 Spring容器中
// The config class is annotated with @ComponentScan -> perform the scan immediately
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();
}
/**
* 扫描到的bean,只要有 @Configuration || @Component || @ComponentScan || @Import || @ImportResource || @Bean 方法
* 进进行配置类的解析
* */
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
// 扫描的结果是配置类,就按照解析配置类的规则解析
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
/**
* 处理 @Import
*
* getImports(sourceClass) 就是拿到类上所有的@Import注解(会递归找)
* */
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
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);
}
}
/**
* 【@Bean 第一步】处理附加的 @Bean 方法,在这里会把@Bean 标记的方法,先存起来
* */
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
/**
* 就是将 sourceClass 的接口递归拿到 @Bean的方法,将方法信息记录到 configClass 中
* */
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
/**
* 【@Bean 第二步】针对父类里面有@Bean的方法,会把已经处理过的父类 存到 knownSuperclasses 这个Map中,避免重复处理
* 所以但我们使用SpringBoot+SpringMVC的时,注册多个 WebMvcConfigurationSupport 子类时候 发现只有一个子类会生效。就是因为这个机制保证了父类里面的@Bean方法只会被注册一次
* */
// 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;
}
/**
* 注册恰好是配置类本身的成员(嵌套)类。
*/
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
if (!memberClasses.isEmpty()) {
List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
for (SourceClass memberClass : memberClasses) {
// 内部类 是 配置类
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata())
&& !memberClass.getMetadata()
.getClassName()
.equals(configClass.getMetadata()
.getClassName())) {
// 记录一下
candidates.add(memberClass);
}
}
OrderComparator.sort(candidates);
for (SourceClass candidate : candidates) {
if (this.importStack.contains(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
this.importStack.push(configClass);
try {
/**
* 解析配置类。
* 记录信息:candidate 的 {@link ConfigurationClass#importedBy} 是 configClass
* */
processConfigurationClass(candidate.asConfigClass(configClass), filter);
} finally {
this.importStack.pop();
}
}
}
}
}
/**
* 处理给定<code>的@PropertySource</code>注释元数据。
*
* @param 找到<code>@PropertySource</code>注释的 propertySource 元数据
* 如果加载属性源失败,则@throws IOException
*/
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
// name
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
// 编码
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
// 要加载的属性文件
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
// 忽略资源找不到
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
// 拿到 PropertySourceFactory
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
/**
* 注:默认是 DefaultPropertySourceFactory ,否则就反射实例化得到 PropertySourceFactory 。
* DefaultPropertySourceFactory 不支持解析yml格式的内容,所以要想导入 yml 格式的内容需要自定义。
*
* {@link YamlPropertiesFactoryBean#getObject()} 这个是Spring提供的,可解析yml内容成Properties对象,有了Properties对象
* 就可以构造出 PropertySource 对象
* */
PropertySourceFactory factory = (factoryClass
== PropertySourceFactory.class ? DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
// 遍历 locations
for (String location : locations) {
try {
/**
* 解析占位符,也就是说可以这么写 @PropertySource("${prop_file}")
* */
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
/**
* 获取资源文件,这里会处理 classpath: 前缀
* {@link GenericApplicationContext#getResource(String)}
* {@link DefaultResourceLoader#getResource(String)}
* */
Resource resource = this.resourceLoader.getResource(resolvedLocation);
/**
* 一个 location 对应一个 PropertySource 然后记录到环境变量中 {@link AbstractEnvironment#propertySources}
* {@link DefaultPropertySourceFactory#createPropertySource(String, EncodedResource)}
*
* 注:
* 1. name是null,就会根据 EncodedResource 生成名字,默认就是资源文件的路径
* 2. 添加的特点是后添加会放到前面
* */
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
} catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
// Placeholders not resolvable or resource not found when trying to open it
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
} else {
throw ex;
}
}
}
}
private void addPropertySource(PropertySource<?> propertySource) {
String name = propertySource.getName();
MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
// 已经添加过了
if (this.propertySourceNames.contains(name)) {
// 已经添加过了,那就对已有的属性值进行扩展
// We've already added a version, we need to extend it
PropertySource<?> existing = propertySources.get(name);
if (existing != null) {
// 拿到新加的 PropertySource
PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ? ((ResourcePropertySource) propertySource).withResourceName() : propertySource);
if (existing instanceof CompositePropertySource) {
/**
* 将新添加的扩展到 现有的里面,newSource 放到集合的前面,从而保证优先使用
* */
((CompositePropertySource) existing).addFirstPropertySource(newSource);
} else {
// 将现有的 换成 CompositePropertySource 类型的对象
if (existing instanceof ResourcePropertySource) {
existing = ((ResourcePropertySource) existing).withResourceName();
}
CompositePropertySource composite = new CompositePropertySource(name);
// newSource 放到集合的前面,从而保证优先使用
composite.addPropertySource(newSource);
composite.addPropertySource(existing);
// 替换掉
propertySources.replace(name, composite);
}
// 结束
return;
}
}
if (this.propertySourceNames.isEmpty()) {
// 添加
propertySources.addLast(propertySource);
} else {
// 拿到最后一个
String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
// 放到最后一个之前。也就是说 新添加的的会放在前面
propertySources.addBefore(firstProcessed, propertySource);
}
// 记录
this.propertySourceNames.add(name);
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
this.importStack.push(configClass);
try {
// 遍历所有 @Import的值
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
} else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
} 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 = ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
} else {
/**
* 兜底,记录导入的类和其对应的元数据
* 这个元数据是在 {@link ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor#postProcessBeforeInitialization(Object, String)} 会用到
*
* 比如:@Import(A.class),是给A.class作为key,value就是元数据
* */
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata()
.getClassName());
/**
* 解析配置类。
* 记录信息:candidate 的 {@link ConfigurationClass#importedBy} 是 configClass
* */
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
} 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();
}
}
}
/**
* 检索所有<code>@Bean</code>方法的元数据。
*/
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
AnnotationMetadata original = sourceClass.getMetadata();
Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
// Try reading the class file via ASM for deterministic declaration order...
// Unfortunately, the JVM's standard reflection returns methods in arbitrary
// order, even between different runs of the same application on the same JVM.
try {
AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader(original.getClassName())
.getAnnotationMetadata();
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
if (asmMethods.size() >= beanMethods.size()) {
Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
for (MethodMetadata asmMethod : asmMethods) {
for (MethodMetadata beanMethod : beanMethods) {
if (beanMethod.getMethodName()
.equals(asmMethod.getMethodName())) {
selectedMethods.add(beanMethod);
break;
}
}
}
if (selectedMethods.size() == beanMethods.size()) {
// All reflection-detected methods found in ASM method set -> proceed
beanMethods = selectedMethods;
}
}
} catch (IOException ex) {
logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
// No worries, let's continue with the reflection metadata we started with...
}
}
return beanMethods;
}
/**
* 在配置类实现的接口上注册默认方法。
*/
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
// 遍历接口
for (SourceClass ifc : sourceClass.getInterfaces()) {
// 接口中有@Bean的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
for (MethodMetadata methodMetadata : beanMethods) {
// 不是抽象方法,才记录到 configClass 中
if (!methodMetadata.isAbstract()) {
// A default method or other concrete method on a Java 8+ interface...
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
}
// 递归处理接口的接口
processInterfaces(configClass, ifc);
}
}
ComponentScanAnnotationParser
ComponentScanAnnotationParser:
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
// 默认为 AnnotationBeanNameGenerator
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass));
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);
}
}
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);
}
});
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
/**
* 包扫描 BeanDefinition
* 在指定的基础包中执行扫描,
* 返回已注册的 Bean 定义。
* <p>此方法<i>不</i>注册注解配置处理器
* 而是将此留给调用方。
*
* @param basePackages the packages to check for annotated classes
* @return set of beans registered if any for tooling registration purposes (never {@code null})
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 创建bean定义的 holder对象用于保存扫描后生成的bean定义对象
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 循环我们的包路径集合
for (String basePackage : basePackages) {
// 查找符合条件的 bean
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 获取 @Scope 的信息
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 设置beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 处理 @Autowired 相关的
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 处理jsr250相关的组件
if (candidate instanceof AnnotatedBeanDefinition) {
// 解析 @Lazy、@Primary、@DependsOn、@Role、@Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 检查 Spring 容器中是否已经存在该 beanName
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
/**
* 针对 @Scope 进行处理,只要不是 @Scope(proxyMode = ScopedProxyMode.NO | DEFAULT) 就做额外处理。
* 具体的处理逻辑是 额外注册一个 BeanDefinition 记录的是原始BeanDefinition,其beanName是 `scopedTarget. + 当前beanName`
* 然后返回的是 处理后的BeanDefinition,其实就是修改 beanClass 为 ScopedProxyFactoryBean 这个类型
*
* {@link ScopedProxyUtils#createScopedProxy(BeanDefinitionHolder, BeanDefinitionRegistry, boolean)}
* */
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册到 IOC 容器中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
ConfigurationClassBeanDefinitionReader
/**
*读取 {@code configurationModel},注册 Bean 定义
* 根据注册表的内容。
*/
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
/**
* 读取特定的 {@link ConfigurationClass},注册 Bean 定义
* 用于类本身及其所有 {@link Bean} 方法。
*/
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 会进行 @Conditional 校验,应该跳过 就不注册到BeanDefinitionMap了
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
// 是通过 @Import 导入的类,或者是成员内部类是配置类的情况
if (configClass.isImported()) {
/**
* 这些配置类比较特殊,还没有注册到BeanFactory中,所以这一步是将这种配置到注册到BeanFactory
* */
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
/**
* 【@Bean 第四步】将配置类里面的@Bean方法,解析成beanDefinition,然后注册到 beanDefinitionMap 中
* */
loadBeanDefinitionsForBeanMethod(beanMethod);
}
/**
* 加载 @ImportResource
* 会使用 XmlBeanDefinitionReader 进行读取和解析
* {@link XmlBeanDefinitionReader#loadBeanDefinitions(Resource)}
* {@link XmlBeanDefinitionReader#doLoadBeanDefinitions(InputSource, Resource)}
* */
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
/**
* 回调 {@link ImportBeanDefinitionRegistrar#registerBeanDefinitions(AnnotationMetadata, BeanDefinitionRegistry, BeanNameGenerator)}
* ioc 容器已经作为入参传入了,你想做啥任你开心
* */
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
/**
* 将 {@link Configuration} 类本身注册为 Bean 定义。
*/
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
// 拿到 @Scope 信息
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
// 就是将通用的注解值 设置到 BeanDefinition中
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
/**
* 看看是否需要做 额外处理,和这里是一样的逻辑
* {@link ClassPathBeanDefinitionScanner#doScan(String...)}
* */
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isTraceEnabled()) {
logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
}
}
配置类增强流程
如果一个配置类是Full模式,那么它就需要被CGLIB字节码增强。
增强动作委托给enhanceConfigurationClasses(beanFactory)
去完成。
如果是full配置类会使用Cglib生成代理类,然后将代理类覆盖掉原来BeanDefinition记录的beanClass。
ConfigurationClassPostProcessor
/**
* 准备用于在运行时处理 Bean 请求的配置类
* 将它们替换为 CGLIB 增强的子类。
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
// 防止重复处理
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
// 在执行postProcessBeanDefinitionRegistry方法的时就已经将
// 这个id添加到registriesPostProcessed集合中了
// 所以到这里就不会再重复执行配置类的解析了(解析@Import、@Bean等)
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor 钩子显然不受支持...此时只需延迟调用 processConfigurationClasses。
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
/**
* 增强配置类class
*/
enhanceConfigurationClasses(beanFactory);
/**
* 添加一个后置处理器,用来处理 ImportAware接口、给full配置类设置属性
* */
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
/**
* 这里就是区别 full配置类 和 lite配置类的地方了。如果是full配置类会使用Cglib生成代理类,然后将代理类覆盖掉原来BeanDefinition记录的beanClass
* 对 BeanFactory 进行后处理以搜索配置类 BeanDefinitions;
* 然后,任何候选项都会通过 {@link ConfigurationClassEnhancer} 进行增强。
* 候选状态由 BeanDefinition 属性元数据确定。
* @see ConfigurationClassEnhancer
*/
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
// 记录full配置类
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
AnnotationMetadata annotationMetadata = null;
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
annotationMetadata = annotatedBeanDefinition.getMetadata();
methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
}
/**
* 在这里标记是full配置类还是lite配置类 {@link ConfigurationClassUtils#checkConfigurationClassCandidate(BeanDefinition, MetadataReaderFactory)}
* */
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
// or component class without @Bean methods.
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
// 是 lite配置类 但是没有 @Bean方法
boolean liteConfigurationCandidateWithoutBeanMethods = (
ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr)
&& annotationMetadata != null
&& !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
// 记录
abd.resolveBeanClass(this.beanClassLoader);
} catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
}
// 是 full 配置类
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName
+ "' since it is not stored in an AbstractBeanDefinition subclass");
} else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName
+ "' since its singleton instance has been created too early. The typical cause "
+ "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor "
+ "return type: Consider declaring such methods as 'static'.");
}
// 记录
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
// nothing to enhance -> return immediately
enhanceConfigClasses.end();
return;
}
// 这里就是遍历所有的 full配置类,使用cglib生成代理类的class
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 class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
/**
* 这里就是使用cglib生成代理类
* */
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with "
+ "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
// 将cglib生成的class 设置到BeanDefinition中
beanDef.setBeanClass(enhancedClass);
}
}
enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet()
.size()))
.end();
}
ConfigurationClassEnhancer
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
// cglib生成的代理类就是会实现 EnhancedConfiguration ,所以这里的目的防止重复代理
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Ignoring request to enhance %s as it has " +
"already been enhanced. This usually indicates that more than one " +
"ConfigurationClassPostProcessor has been registered (e.g. via " +
"<context:annotation-config>). This is harmless, but you may " +
"want check your configuration and remove one CCPP if possible",
configClass.getName()));
}
return configClass;
}
/**
* cglib生成代理类class
*
*
* CallbackFilter是ConditionalCallbackFilter
* 逻辑很简单
* - 是@Bean标注的方法,生成的字节码使用的callback是 BeanMethodInterceptor
* - 方法是 setBeanFactory,生成的字节码使用的callback是 BeanFactoryAwareMethodInterceptor
*
* Callback是 {@link ConfigurationClassEnhancer#CALLBACKS}
* BeanMethodInterceptor
* BeanFactoryAwareMethodInterceptor
*
* @Bean方法的callback逻辑 {@link BeanMethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}
* */
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isTraceEnabled()) {
logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}
/**
* Creates a new CGLIB {@link Enhancer} instance.
*/
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.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
// 设置 CallBackFilter,这个是在生成字节码的时候使用filter确定每个生成的方法内使用的callback
enhancer.setCallbackFilter(CALLBACK_FILTER);
// 设置 CallBack
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
/**
* Uses enhancer to generate a subclass of superclass,
* ensuring that callbacks are registered for the new subclass.
*/
private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass();
// Registering callbacks statically (as opposed to thread-local)
// is critical for usage in an OSGi environment (SPR-5932)...
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
}
private static final Callback[] CALLBACKS = new Callback[]{
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
拦截器执行流程
什么是动态代理?用通俗的话理解就是:代理的核心逻辑就是依赖于拦截器实现的,可见拦截器(也叫增强)之于代理类是何等重要。
上面的三个拦截器中,NoOp.INSTANCE
代表什么都没做,因此我们只需要关注前两个。他俩均是MethodInterceptor
接口的实现类,均实现了intercept()
方法来做具体的拦截操作(他俩均是私有静态内部类哟)。
BeanFactoryAwareMethodInterceptor拦截流程
拦截setBeanFactory()
方法的执行
执行时机决定了增强逻辑何时执行,毕竟一般来说都不可能是增强所有的嘛。
我们知道setBeanFactory()
方法是由Spring容器在初始化Bean时回调调用的,而代理类实现了EnhancedConfiguration
接口(间接实现了BeanFactoryAware
接口),所以该拦截器的执行时机为:在Spring初始化代理类实例时执行拦截。
作为一个拦截器,增强逻辑才是它的核心。
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 找到本类(代理类)里名为`$$beanFactory`的字段
// 若没找到直接报错。若找到了此字段,就给此字段赋值
Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated BeanFactory field");
field.set(obj, args[0]);
// Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
// If so, call its setBeanFactory() method. If not, just exit.
// 如果用户类(也就是你自己定义的类)自己实现了该接口,那么别担心,也会给你赋值上
if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
return proxy.invokeSuper(obj, args);
}
return null;
}
@Override
public boolean isMatch(Method candidateMethod) {
// 当执行到setBeanFactory(xxx)方法时匹配成功
return isSetBeanFactory(candidateMethod);
}
public static boolean isSetBeanFactory(Method candidateMethod) {
return (candidateMethod.getName().equals("setBeanFactory") &&
candidateMethod.getParameterCount() == 1 &&
BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
}
}
从执行时机知道了,它拦截的是setBeanFactory()
方法的执行。所以这里的Method就代表的是setBeanFactory()
方法,Object[] args
的值是当前容器的BeanFactory工厂(注意理解这句话)实例。
🔥BeanMethodInterceptor拦截流程
拦截任何标注有@Bean
注解的方法的调用,以确保正确处理Bean语义,例如作用域(请别忽略它)和AOP代理。
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
/**
* Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
* existence of this bean object.
* @throws Throwable as a catch-all for any exception that may be thrown when invoking the
* super implementation of the proxied method i.e., the actual {@code @Bean} method
*/
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// 拿到 BeanFactory
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
/**
* 拿到beanName:有@Bean就返回其属性值,是数组只会返回第一个 -> 方法名
*
* @Bean({"a", "a2"})
* @Scope(proxyMode = ScopedProxyMode.NO)
* public Test a() {
* return null;
* }
* */
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// 只要不是 @Scope(proxyMode = ScopedProxyMode.NO) 就是true
// Determine whether this bean is a scoped-proxy
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
// 拼接上前缀 scopedTarget.
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
// To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances.
/**
* beanName是FactoryBean 且 不是真正创建的bean
* */
// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// This ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
// 使用BeanFactory实例化工厂bean
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
//作用域代理工厂 Bean 是一种特例,不应进一步代理
} else {
/**
* 使用JDk代理,拦截{@link FactoryBean#getObject()}方法
* */
//它是候选的 FactoryBean - 继续进行增强
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
/**
* 通过ThreadLocal来记录当前调用的方法,当循环调用@Bean 方法时,第一次是代理对象方法,再调第二次就是执行的父类方法(也就是被代理类的方法)
* */
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (logger.isInfoEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
"@Resource and @PostConstruct within the method's declaring " +
"@Configuration class. Add the 'static' modifier to this method to avoid " +
"these container lifecycle issues; see @Bean javadoc for complete details.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}
/**
* enhancedConfigInstance 这个是代理对象
* invokeSuper 就是反射执行代理对象父类的方法,也就是执行被代理对象方法
* */
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
/**
* 解析bean引用。说白了就是从BeanFactory找Bean,单例池中没得就会实例化bean,实例化的时候就会往ThreadLocal记录一下,
* 然后再执行代理对象的方法进行实例化,也就是会回调到当前方法 {@link BeanMethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}
* 因为实例化的时候记录了当前方法,所以回调到当前方法满足 isCurrentlyInvokedFactoryMethod 条件,所以就是 super.method 进行实例化
* */
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
ConfigurableBeanFactory beanFactory, String beanName) {
// The user (i.e. not the factory) is requesting this bean through a call to
// the bean method, direct or indirect. The bean may have already been marked
// as 'in creation' in certain autowiring scenarios; if so, temporarily set
// the in-creation status to false in order to avoid an exception.
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, false);
}
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
if (useArgs && beanFactory.isSingleton(beanName)) {
// Stubbed null arguments just for reference purposes,
// expecting them to be autowired for regular singleton references?
// A safe assumption since @Bean singleton arguments cannot be optional...
for (Object arg : beanMethodArgs) {
if (arg == null) {
useArgs = false;
break;
}
}
}
/**
* 实例化的时候会标记
* {@link SimpleInstantiationStrategy#instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object...)}
* */
// getBean
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
// bean实例和方法返回值类型 不匹配
if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
// Detect package-protected NullBean instance through equals(null) check
if (beanInstance.equals(null)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("@Bean method %s.%s called as bean reference " +
"for type [%s] returned null bean; resolving to null value.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName()));
}
beanInstance = null;
} else {
String msg = String.format("@Bean method %s.%s called as bean reference " +
"for type [%s] but overridden by non-compatible bean instance of type [%s].",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
try {
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
} catch (NoSuchBeanDefinitionException ex) {
// Ignore - simply no detailed message then.
}
// 报错
throw new IllegalStateException(msg);
}
}
// 是正在调用的方法,就是在调用@Bean方法
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
if (currentlyInvoked != null) {
String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
// 注册依赖关系
beanFactory.registerDependentBean(beanName, outerBeanName);
}
// 返回bean实例
return beanInstance;
} finally {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, true);
}
}
}
@Override
public boolean isMatch(Method candidateMethod) {
return (candidateMethod.getDeclaringClass() != Object.class &&
!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
}
private ConfigurableBeanFactory getBeanFactory(Object enhancedConfigInstance) {
// 拿到字段
Field field = ReflectionUtils.findField(enhancedConfigInstance.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated bean factory field");
// 拿到字段的值
Object beanFactory = ReflectionUtils.getField(field, enhancedConfigInstance);
Assert.state(beanFactory != null, "BeanFactory has not been injected into @Configuration class");
Assert.state(beanFactory instanceof ConfigurableBeanFactory,
"Injected BeanFactory is not a ConfigurableBeanFactory");
return (ConfigurableBeanFactory) beanFactory;
}
/**
* Check the BeanFactory to see whether the bean named <var>beanName</var> already
* exists. Accounts for the fact that the requested bean may be "in creation", i.e.:
* we're in the middle of servicing the initial request for this bean. From an enhanced
* factory method's perspective, this means that the bean does not actually yet exist,
* and that it is now our job to create it for the first time by executing the logic
* in the corresponding factory method.
* <p>Said another way, this check repurposes
* {@link ConfigurableBeanFactory#isCurrentlyInCreation(String)} to determine whether
* the container is calling this method or the user is calling this method.
* @param beanName name of bean to check for
* @return whether <var>beanName</var> already exists in the factory
*/
private boolean factoryContainsBean(ConfigurableBeanFactory beanFactory, String beanName) {
return (beanFactory.containsBean(beanName) && !beanFactory.isCurrentlyInCreation(beanName));
}
/**
* Check whether the given method corresponds to the container's currently invoked
* factory method. Compares method name and parameter types only in order to work
* around a potential problem with covariant return types (currently only known
* to happen on Groovy classes).
*/
private boolean isCurrentlyInvokedFactoryMethod(Method method) {
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
}
/**
* Create a subclass proxy that intercepts calls to getObject(), delegating to the current BeanFactory
* instead of creating a new instance. These proxies are created only when calling a FactoryBean from
* within a Bean method, allowing for proper scoping semantics even when working against the FactoryBean
* instance directly. If a FactoryBean instance is fetched through the container via &-dereferencing,
* it will not be proxied. This too is aligned with the way XML configuration works.
*/
private Object enhanceFactoryBean(final Object factoryBean, Class<?> exposedType,
final ConfigurableBeanFactory beanFactory, final String beanName) {
try {
Class<?> clazz = factoryBean.getClass();
boolean finalClass = Modifier.isFinal(clazz.getModifiers());
boolean finalMethod = Modifier.isFinal(clazz.getMethod("getObject").getModifiers());
// 类是final 或者 getObject方法是final的
if (finalClass || finalMethod) {
// 返回值是接口类型才创建代理对象
if (exposedType.isInterface()) {
if (logger.isTraceEnabled()) {
logger.trace("Creating interface proxy for FactoryBean '" + beanName + "' of type [" +
clazz.getName() + "] for use within another @Bean method because its " +
(finalClass ? "implementation class" : "getObject() method") +
" is final: Otherwise a getObject() call would not be routed to the factory.");
}
// 使用JDK代理
return createInterfaceProxyForFactoryBean(factoryBean, exposedType, beanFactory, beanName);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Unable to proxy FactoryBean '" + beanName + "' of type [" +
clazz.getName() + "] for use within another @Bean method because its " +
(finalClass ? "implementation class" : "getObject() method") +
" is final: A getObject() call will NOT be routed to the factory. " +
"Consider declaring the return type as a FactoryBean interface.");
}
return factoryBean;
}
}
} catch (NoSuchMethodException ex) {
//没有 getObject() 方法 -> 不应该发生,但只要没有人试图调用它......
}
return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
}
private Object createInterfaceProxyForFactoryBean(final Object factoryBean, Class<?> interfaceType,
final ConfigurableBeanFactory beanFactory, final String beanName) {
return Proxy.newProxyInstance(
factoryBean.getClass().getClassLoader(), new Class<?>[]{interfaceType},
(proxy, method, args) -> {
// 只代理 getObject 方法
if (method.getName().equals("getObject") && args == null) {
return beanFactory.getBean(beanName);
}
return ReflectionUtils.invokeMethod(method, factoryBean, args);
});
}
private Object createCglibProxyForFactoryBean(final Object factoryBean,
final ConfigurableBeanFactory beanFactory, final String beanName) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(factoryBean.getClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallbackType(MethodInterceptor.class);
// Ideally create enhanced FactoryBean proxy without constructor side effects,
// analogous to AOP proxy creation in ObjenesisCglibAopProxy...
Class<?> fbClass = enhancer.createClass();
Object fbProxy = null;
if (objenesis.isWorthTrying()) {
try {
fbProxy = objenesis.newInstance(fbClass, enhancer.getUseCache());
} catch (ObjenesisException ex) {
logger.debug("Unable to instantiate enhanced FactoryBean using Objenesis, " +
"falling back to regular construction", ex);
}
}
if (fbProxy == null) {
try {
fbProxy = ReflectionUtils.accessibleConstructor(fbClass).newInstance();
} catch (Throwable ex) {
throw new IllegalStateException("Unable to instantiate enhanced FactoryBean using Objenesis, " +
"and regular FactoryBean instantiation via default constructor fails as well", ex);
}
}
((Factory) fbProxy).setCallback(0, (MethodInterceptor) (obj, method, args, proxy) -> {
if (method.getName().equals("getObject") && args.length == 0) {
return beanFactory.getBean(beanName);
}
return proxy.invoke(factoryBean, args);
});
return fbProxy;
}
}
执行时机:
@Override
public boolean isMatch(Method candidateMethod) {
return (candidateMethod.getDeclaringClass() != Object.class &&
!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
}
三个条件:
- 该方法不能是Object的方法(即使你Object的方法标注了@Bean,我也不认)。
- 不能是
setBeanFactory()
方法。这很容易理解,它交给上个拦截器搞定即可。 - 方法必须标注标注有@Bean注解。
执行逻辑:
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// 拿到 BeanFactory
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
/**
* 拿到beanName:有@Bean就返回其属性值,是数组只会返回第一个 -> 方法名
*
* @Bean({"a", "a2"})
* @Scope(proxyMode = ScopedProxyMode.NO)
* public Test a() {
* return null;
* }
* */
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// 只要不是 @Scope(proxyMode = ScopedProxyMode.NO) 就是true
// Determine whether this bean is a scoped-proxy
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
// 拼接上前缀 scopedTarget.
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
// To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances.
/**
* beanName是FactoryBean 且 不是真正创建的bean
* */
// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// This ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
// 使用BeanFactory实例化工厂bean
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
//作用域代理工厂 Bean 是一种特例,不应进一步代理
} else {
/**
* 使用JDk代理,拦截{@link FactoryBean#getObject()}方法
* */
//它是候选的 FactoryBean - 继续进行增强
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
/**
* 通过ThreadLocal来记录当前调用的方法,当循环调用@Bean 方法时,第一次是代理对象方法,再调第二次就是执行的父类方法(也就是被代理类的方法)
* */
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (logger.isInfoEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
"@Resource and @PostConstruct within the method's declaring " +
"@Configuration class. Add the 'static' modifier to this method to avoid " +
"these container lifecycle issues; see @Bean javadoc for complete details.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}
/**
* enhancedConfigInstance 这个是代理对象
* invokeSuper 就是反射执行代理对象父类的方法,也就是执行被代理对象方法
* */
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
/**
* 解析bean引用。说白了就是从BeanFactory找Bean,单例池中没得就会实例化bean,实例化的时候就会往ThreadLocal记录一下,
* 然后再执行代理对象的方法进行实例化,也就是会回调到当前方法 {@link BeanMethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}
* 因为实例化的时候记录了当前方法,所以回调到当前方法满足 isCurrentlyInvokedFactoryMethod 条件,所以就是 super.method 进行实例化
* */
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
// 创建一个子类代理,拦截对getObject()的调用,委托给当前的BeanFactory
// 而不是创建一个新的实例。这些代理仅在调用FactoryBean时创建
// factoryBean:从容器内拿出来的那个已经存在的工厂Bean实例(是工厂Bean实例)
// exposedType:@Bean标注的方法的返回值类型
private Object enhanceFactoryBean(Object factoryBean, Class<?> exposedType,
ConfigurableBeanFactory beanFactory, String beanName) {
try {
// 看看Spring容器内已经存在的这个工厂Bean的情况,看看是否有final
Class<?> clazz = factoryBean.getClass();
boolean finalClass = Modifier.isFinal(clazz.getModifiers());
boolean finalMethod = Modifier.isFinal(clazz.getMethod("getObject").getModifiers());
// 类和方法其中有一个是final,那就只能看看能不能走接口代理喽
if (finalClass || finalMethod) {
// @Bean标注的方法返回值若是接口类型 尝试走基于接口的JDK动态代理
if (exposedType.isInterface()) {
// 基于JDK的动态代理
return createInterfaceProxyForFactoryBean(factoryBean, exposedType, beanFactory, beanName);
} else {
// 类或方法存在final情况,但是呢返回类型又不是
return factoryBean;
}
}
}
catch (NoSuchMethodException ex) {
// 没有getObject()方法 很明显,一般不会走到这里
}
// 到这,说明以上条件不满足:存在final且还不是接口类型
// 类和方法都不是final,生成一个CGLIB的动态代理
return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
}
说明:无论是JDK动态代理还是CGLIB的代理实现均非常简单,就是把getObject()方法代理为使用
beanFactory.getBean(beanName)
去获取实例(要不代理掉的话,每次不就执行你getObject()里面的逻辑了麽,就又会创建新实例啦~)
lite模式和full模式的区别
lite模式:
官方定义为:在没有标注@Configuration
的类里面有@Bean
方法就称为Lite模式的配置。透过源码再看这个定义是不完全正确的,而应该是有如下case均认为是Lite模式的配置类:
- 类上标注有
@Component
注解 - 类上标注有
@ComponentScan
注解 - 类上标注有
@Import
注解 - 类上标注有
@ImportResource
注解 - 若类上没有任何注解,但类内存在@Bean方法
以上case的前提均是类上没有被标注@Configuration
,在Spring 5.2之后新增了一种case也算作Lite模式:
标注有@Configuration(proxyBeanMethods = false)
,注意:此值默认是true哦,需要显示改为false才算是Lite模式。
优点:
- 运行时不再需要给对应类生成CGLIB子类,提高了运行性能,降低了启动时间
- 可以该配置类当作一个普通类使用喽:也就是说@Bean方法 可以是private、可以是final
缺点:
- 不能声明@Bean之间的依赖,也就是说不能通过方法调用来依赖其它Bean
- (其实这个缺点还好,很容易用其它方式“弥补”,比如:把依赖Bean放进方法入参里即可)
Full模式:
标注有@Configuration
注解的类被称为full模式的配置类。自Spring5.2后这句话改为下面这样我觉得更为精确些:
- 标注有
@Configuration
或者@Configuration(proxyBeanMethods = true)
的类被称为Full模式的配置类 - (当然喽,proxyBeanMethods属性的默认值是true,所以一般需要Full模式我们只需要标个注解即可)
优点:
- 可以支持通过常规Java调用相同类的@Bean方法而保证是容器内的Bean,这有效规避了在“Lite模式”下操作时难以跟踪的细微错误。特别对于萌新程序员,这个特点很有意义
缺点:
- 运行时会给该类生成一个CGLIB子类放进容器,有一定的性能、时间开销(这个开销在Spring Boot这种拥有大量配置类的情况下是不容忽视的,这也是为何Spring 5.2新增了
proxyBeanMethods
属性的最直接原因) - 正因为被代理了,所以@Bean方法 不可以是private、不可以是final