在前文 spring 中包自动扫描之 component-scan 解析 一文中我们知道,待扫描结束后,注册了一堆注解模式下相关的后置处理器,其中一个就是 ConfigurationClassPostProcessor,从类名猜测主要是针对配置类的,下面我们就来看看这个类到底是什么,以及在 spring 中的作用是什么。
实例化
先来看下这个类的结构图。
从图中可知,这是一个 BeanFactoryPostProcessor,在 AbstractApplicationContext#refresh 中,当 beanFactory 初始化完成之后,会调用 AbstractApplicationContext#invokeBeanFactoryPostProcessors。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 处理参数 beanFactoryPostProcessors
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先,调用实现了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// 接着,调用实现了 Ordered 的 BeanDefinitionRegistryPostProcessor
...
// 最后,调用剩下的 BeanDefinitionRegistryPostProcessor
...
// 调用 postProcessBeanFactory 回调
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 处理 BeanFactoryPostProcessor
...
beanFactory.clearMetadataCache();
}
ConfigurationClassPostProcessor 既实现了 BeanDefinitionRegistryPostProcessor,又实现了 PriorityOrdered,所以会被第一个处理,调用 beanFactory.getBean 进行实例对象的创建获取。
有一点需要注意,就是实例化完成,进行初始化时,在 AbstractAutowireCapableBeanFactory#initializeBean 中调用 invokeAwareMethods,此时由于实现了 BeanClassLoaderAware 接口,会执行 setBeanClassLoader。
// initializeBean --> invokeAwareMethods
@Override
public void setBeanClassLoader(ClassLoader beanClassLoader) {
this.beanClassLoader = beanClassLoader;
if (!this.setMetadataReaderFactoryCalled) {
// 赋值
this.metadataReaderFactory = new CachingMetadataReaderFactory(beanClassLoader);
}
}
public CachingMetadataReaderFactory(@Nullable ClassLoader classLoader) {
super(classLoader);
setCacheLimit(DEFAULT_CACHE_LIMIT);
}
// CachingMetadataReaderFactory 父类
public SimpleMetadataReaderFactory(@Nullable ClassLoader classLoader) {
this.resourceLoader =
(classLoader != null ? new DefaultResourceLoader(classLoader) : new DefaultResourceLoader());
}
可以看到对 ConfigurationClassPostProcessor 中 metadataReaderFactory 进行了赋值,并对 CachingMetadataReaderFactory 父类 SimpleMetadataReaderFactory 中 resourceLoader 也进行了赋值。
接着,由于前面注册了 ApplicationContextAwareProcessor 的缘故,会调用 ApplicationContextAwareProcessor#postProcessBeforeInitialization,在其中执行 invokeAwareInterfaces,会执行 setEnvironemnt 和 setResourceLoader。
执行 setResourceLoader 时会将当前 ApplicationContext 作为 ResourceLoader 传入。
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
this.resourceLoader = resourceLoader;
if (!this.setMetadataReaderFactoryCalled) {
// 赋值
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
}
}
public CachingMetadataReaderFactory(@Nullable ResourceLoader resourceLoader) {
super(resourceLoader);
if (resourceLoader instanceof DefaultResourceLoader) {
// 赋值
this.metadataReaderCache =
((DefaultResourceLoader) resourceLoader).getResourceCache(MetadataReader.class);
}
else {
setCacheLimit(DEFAULT_CACHE_LIMIT);
}
}
对之前 invokeAwareMethods 中 调用 setBeanClassLoader 时赋值的 metadataReaderFactory 和 resourceLoader 都进行了覆盖,并且对 CachingMetadataReaderFactory 中 metadataReaderCache 进行了赋值。
// DefaultResourceLoader
public <T> Map<Resource, T> getResourceCache(Class<T> valueType) {
return (Map<Resource, T>) this.resourceCaches.computeIfAbsent(valueType, key -> new ConcurrentHashMap<>());
}
所以,同一个 AbstractApplicationContext 下,共用同一个 DefaultResourceLoader,由于在包的扫描时访问过包下的字节码文件,resourceCaches 中 key 为 MetadataReader.class,所以此时返回给 metadataReaderCache 赋值的 ConcurrentHashMap 包含之前访问到的资源和 MetadataReader 对象。
这样,就完成了 ConfigurationClassPostProcessor 的实例化。
顺便说下,目前在 spring 中,BeanDefinitionRegistryPostProcessor 的实现类只有 ConfigurationClassPostProcessor 一个。
配置类的处理 invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw ...
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw ...
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
针对每一个 BenDefinitionRegistry,即 BeanFactory,生成一个 registryId,用来表示只执行一次。
下面来看看 processConfigBeanDefinitions 具体做了什么。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历注册的 BeanDefinition 名称
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
...
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 没有找到 @Configuration 修饰的类,立即返回
if (configCandidates.isEmpty()) {
return;
}
// 根据 @Order 排序
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) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
// null
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
// 不为 null
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 解析每一个配置类,先创建一个解析器
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");
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 基于配置类内容,创建 BeanDefinition,并完成注册
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);
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());
}
// 遍历新的候选名称,找出新注册的 beanDefinition,判断是否是配置类,是配置类,且未被处理,将再次加入 candidates,开启下一次循环
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());
// // 注册 ImportRegistry 作为一个单例对象,为了支持ImportAware @Configuration类
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
先遍历注册的 BeanDefintion 名称,检查是否是配置类,是,加入 configCandidates 候选集合。
// ConfigurationClassUtils
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())) {
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// 检查已经加载的 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) {
return false;
}
}
// 判断是否持有 @Configuration 注解,如果持有获取其注解属性
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
// 控制是否对配置类进行增强
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// 是配置类,获取 @Order 属性
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
// 不考虑接口
if (metadata.isInterface()) {
return false;
}
// 持有这四个中一个 @Component/@ComponentScan/@Import/@ImportResource
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// 最后,查找 @Bean 方法
return hasBeanMethods(metadata);
}
先判断是否直接持有 @Configuration,没有,再调用 isConfigurationCandidate 进行判断。是接口直接返回 false,否则判断是否持有 @Component、@ComponentScan、@Import、@ImportResource 四个注解中的一个,如果都不存在,最后检查类中是否存在 @Bean 修饰的方法,存在,即视为配置类。
接着,是配置类,获取 @Order 注解属性。
// 获取 @Order 注解属性
@Nullable
public static Integer getOrder(AnnotationMetadata metadata) {
Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
}
接着利用 @Order 属性值对 configCandidates 排序后,进行配置类的解析。先创建一个解析器,ConfigurationClassParser,接着调用 parse 方法,传入 configCandidates 进行解析。
// 配置类解析
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 遍历注册的配置类
for (BeanDefinitionHolder holder : configCandidates) {
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 ...
}
catch (Throwable ex) {
throw ...
}
}
this.deferredImportSelectorHandler.process();
}
根据不同的 BeanDefinition 类型,执行不同的解析策略。不管是哪一种策略,都是先封装成一个 ConfigurationClass 对象,然后调用 ConfigurationClassParser#processConfigurationClass 进行处理。
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) {
if (configClass.isImported()) {
// 两者都是 imported,合并即可,existingClass 为 non-imported,则不处理,之后直接返回
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
return;
}
else {
// configClass 是 non-imported,对 configurationClasses 中的 existingClass 进行替换,此处先进行删除
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);
}
真正处理时,先将其封装成一个 SourceClass 对象。下面来看下封装的过程。
private SourceClass asSourceClass(ConfigurationClass configurationClass, Predicate<String> filter) throws IOException {
AnnotationMetadata metadata = configurationClass.getMetadata();
if (metadata instanceof StandardAnnotationMetadata) {
return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass(), filter);
}
return asSourceClass(metadata.getClassName(), filter);
}
SourceClass asSourceClass(@Nullable String className, Predicate<String> filter) throws IOException {
if (className == null || filter.test(className)) {
return this.objectSourceClass;
}
if (className.startsWith("java")) {
// Never use ASM for core java types
// java 包下的类,去加载,然后封装 SourceClass
try {
return new SourceClass(ClassUtils.forName(className, this.resourceLoader.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new org.springframework.core.NestedIOException("Failed to load class [" + className + "]", ex);
}
}
return new SourceClass(this.metadataReaderFactory.getMetadataReader(className));
}
从前面的介绍可以知道,在创建 ConfigurationClassParser 时,将 ConfigurationClassPostProcessor 中的 metadataReaderFactory 传递给了 ConfigurationClassParser 构造方法,所以此时就是利用这个 metadataReaderFactory 来执行 getMetadataReader 方法获取 MetadataReader。此时的 metadataReaderFactory 为 CachingMetadataReaderFactory,传入 className,调入父类 SimpleMetadataReaderFactory。
@Override
public MetadataReader getMetadataReader(String className) throws IOException {
try {
String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX;
// 处理完 resourcePath = classpath:com/icheetor/annotation/service/impl/UserServiceImpl.class
Resource resource = this.resourceLoader.getResource(resourcePath);
// 调用回子类方法 CachingMetadataReaderFactory#getMetadataReader 去执行
return getMetadataReader(resource);
}
catch (FileNotFoundException ex) {
// 可能是一个内部类,应用了 '.' 语法,此处应使用 '$' 语法
int lastDotIndex = className.lastIndexOf('.');
if (lastDotIndex != -1) {
String innerClassName =
className.substring(0, lastDotIndex) + '$' + className.substring(lastDotIndex + 1);
String innerClassResourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(innerClassName) + ClassUtils.CLASS_FILE_SUFFIX;
Resource innerClassResource = this.resourceLoader.getResource(innerClassResourcePath);
if (innerClassResource.exists()) {
return getMetadataReader(innerClassResource);
}
}
throw ex;
}
}
// DefaultResourceLoader
@Override
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
if (location.startsWith("/")) {
return getResourceByPath(location);
}
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
// 创建一个 ClassPathResource
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// Try to parse the location as a URL...
URL url = new URL(location);
return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
}
catch (MalformedURLException ex) {
// No URL -> resolve as resource path.
return getResourceByPath(location);
}
}
}
先将 className 处理成资源 Resource。前面的介绍,CachingMetadataReaderFactory 中 resourceLoader 为 ApplicationContext,抽象实现 AbstractApplicationContext 继承 DefaultResourceLoader,所以调用 DefaultResourceLoader#getResource 创建一个 ClassPathResource 对象。接着再对这个资源对象,调用 CachingMetadataReaderFactory#getMetadataReader,缓存不存在,调用父类方法 SimpleMetadataReaderFactory#getMetadataReader。
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
接着会再次通过 ASM 中的 ClassReader 对字节码文件发起访问,最后返回封装了类相关信息的 SimpleMetadataReader 对象。此处可参考 spring 中的字节码文件访问 – classreading 包。
访问注解时,由于之前包扫描时已经访问过一次,在 AnnotationTypeMappings 中存在 standardRepeatablesCache 缓存,所以直接从缓存中获取到了 AnnotationTypeMappings。只有注解访问结束,即 MergedAnnotationReadingVisitor#visitEnd,调用 MergedAnnotation#of 创建 TypeMappedAnnotation 对象,和整个字节码文件访问结束 SimpleAnnotationMetadataReadingVisitor#visitEnd,调用MergedAnnotations#of 创建 MergedAnnotationsCollection 对象,这两个对象为新建的,但这两个创建过程都不是耗时操作,只有针对某个 annotationType 创建 AnnotationTypeMappings 比较耗时,但 spring 已通过缓存进行了优化,具体可参靠 spring 中的注解操作 – annotation 包。
public SourceClass(Object source) {
this.source = source;
if (source instanceof Class) {
this.metadata = AnnotationMetadata.introspect((Class<?>) source);
}
else {
this.metadata = ((MetadataReader) source).getAnnotationMetadata();
}
}
获取到 SimpleMetadataReader 之后,调用 SourceClass 构造方法,为 metadata 赋值,即 SimpleAnnotationMetadata 对象。
接着执行真正的解析,ConfigurationClassParser#doProcessConfigurationClass。
配置类解析 doProcessConfigurationClass
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
// 持有 @Component
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 递归处理其内部类,将每个内部类处理成 SourceClass,接着调用 processConfigurationClass
processMemberClasses(configClass, sourceClass, filter);
}
// 处理 @PropertySource 注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
...
}
}
// 处理 @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) {
// 被 @ComponentScan 修饰的配置类,立即扫描
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 检查扫描到的 BeanDefinition,判断是否存在配置类,递归解析
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 注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// 处理 @ImportResource 注解
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 方法
// 遍历类访问时获取到的 SimpleAnnotationMetadata 中 annotatedMethods,判断注解类型是否是 @Bean,是,加入集合返回
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 递归处理接口上的 @Bean 默认方法
processInterfaces(configClass, sourceClass);
// 处理父类
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();
}
}
// 无父类,处理完成
return null;
}
在这里,spring-context 模块下 org.springframework.context.annotation 包中定义的配置类相关注解的解析都实现了。
处理完成之后,将 configClass 加入 configurationClasses。
配置类中 BeanDefinition 的注册 loadBeanDefinitions
对配置类解析完成后,创建一个 ConfigurationClassBeanDefinitionReader 对象,完成对配置类中 BeanDefinition 的加载。
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
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;
}
// configClass 是 imported
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 处理 @Bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
下面主要看下 @Bean 定义的 BeanDefinition 的加载。
// 处理 @Bean
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
// 定义 beanMethod 的配置类
ConfigurationClass configClass = beanMethod.getConfigurationClass();
// SimpleMethodMetadata
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// 判断是否需要跳过
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
// 获取 @Bean 上的属性
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
// 定义 beanName,可以看到,当存在 name 属性时,取第一个,不存在,取方法名作为 beanName
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// 注册别名
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
// 这个 beanName 是否之前已经存在,比如通过 xml 配置过
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw ...
}
return;
}
// 配置类中的 BeanDefinition 定义为 ConfigurationClassBeanDefinition
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
if (metadata.isStatic()) {
// static @Bean method
if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
}
else {
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
}
beanDef.setUniqueFactoryMethodName(methodName);
}
else {
// instance @Bean method
// 将 configClass 的 beanName 作为 beanDef 的 factoryBeanName
beanDef.setFactoryBeanName(configClass.getBeanName());
// methodName 作为 factoryMethodName
beanDef.setUniqueFactoryMethodName(methodName);
}
if (metadata instanceof StandardMethodMetadata) {
beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
}
// 设置注解属性
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
// @Scope,定义在 @Bean 方法上的 @Scope
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// proxyMode 不为 ScopedProxyMode.NO,替换 beanDef
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
}
// 注册 BeanDefinition
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
可以看到,将 @Bean 修饰的方法,最终封装成了一个 BeanDefinition,注册到 BeanFactory 中。
这样也完成了配置类中 BeanDefinition 的加载。
在 ConfigurationClassPostProcessor#processConfigBeanDefinitions 方法的最后,当完成了对所有配置类的所有操作之后,会对 ConfigurationClassPostProcessor 中的 metadataReaderFactory,即 CachingMetadataReaderFactory 进行缓存清除。
public void clearCache() {
if (this.metadataReaderCache instanceof LocalResourceCache) {
synchronized (this.metadataReaderCache) {
this.metadataReaderCache.clear();
}
}
else if (this.metadataReaderCache != null) {
setCacheLimit(DEFAULT_CACHE_LIMIT);
}
}
public void setCacheLimit(int cacheLimit) {
if (cacheLimit <= 0) {
this.metadataReaderCache = null;
}
else if (this.metadataReaderCache instanceof LocalResourceCache) {
((LocalResourceCache) this.metadataReaderCache).setCacheLimit(cacheLimit);
}
else {
this.metadataReaderCache = new LocalResourceCache(cacheLimit);
}
}
通过对 metadataReaderCache 赋值为新建的 LocalResourceCache 对象,完成对缓存的清除。
前面介绍过,目前在 spring 中,BeanDefinitionRegistryPostProcessor 的实现类只有一个,就是 ConfigurationClassPostProcessor,也实现了 PriorityOrdered 接口,所以当创建完 ConfigurationClassPostProcessor 实例对象,调用 invokeBeanDefinitionRegistryPostProcessors 之后,就完成了这部分的处理。
为配置类创建代理 invokeBeanFactoryPostProcessors
接着,调用到目前为止处理过的所有 BeanFactoryPostProcessor 的 postProcessBeanFactory 回调。从前面的类结构可知,ConfigurationClassPostProcessor 也是 BeanFactoryPostProcessor 实现类。
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory);
postProcessBeanFactory.end();
}
}
// ConfigurationClassPostProcessor
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw ...
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// beanFactory 没有处理过,先调用 processConfigBeanDefinitions
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
// 添加 BeanPostProcessor,为增强配置类服务,增强类默认实现 EnhancedConfiguration 接口,是一个标记接口
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
相对于 ConfigurationClassPostProcessor,核心代码就是 enhanceConfigurationClasses,从方法名猜测,这是对配置类的增强。
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
// 遍历注册的 beanName
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();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
boolean liteConfigurationCandidateWithoutBeanMethods =
(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
// 加载 beanClass
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw ...
}
}
}
}
// 只有 configClassAttr 为 "full",才会加入 configBeanDefs
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw ...
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
...
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
// 不需要增强
enhanceConfigClasses.end();
return;
}
// 利用 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);
Class<?> configClass = beanDef.getBeanClass();
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
// 替换
beanDef.setBeanClass(enhancedClass);
}
}
enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
}
在 ConfigurationClassPostProcessor#processConfigBeanDefinitions 时,会调用 ConfigurationClassUtils#checkConfigurationClassCandidate 获取 @Configuration 注解属性,根据配置的 proxyBeanMethods 来决定是否应该对 @Bean 方法进行拦截代理,默认 true。
所以当配置类上注解为 @Configuration 时,会通过 Cglib 为配置类生成一个代理类,即此处的 enhancedClass,作为配置类对应 BeanDefinition 的 beanClass。
这样,在创建配置类所对应的实例对象时,如果进行了增强,则默认实现 EnhancedConfiguration 接口,此时填充对象,会调用 ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#postProcessProperties。
@Override
public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
// postProcessProperties method attempts to autowire other configuration beans.
if (bean instanceof EnhancedConfiguration) {
((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
}
return pvs;
}
此时会调用 setBeanFactory 方法,由于增强时设置了拦截器,会调用到 ConfigurationClassEnhancer$BeanFactoryAwareMethodInterceptor 中intercept 方法,其实就是给增强的代理 bean 对象设置 beanFactory 属性。
接着在初始化时,执行 AbstractAutowireCapableBeanFactory#invokeAwareMethods 时,由于 EnhancedConfiguration 继承 BeanFactoryAware 接口,所以又会调用 ConfigurationClassEnhancer.BeanFactoryAwareMethodInterceptor#intercept 方法。
@Bean 方法
@Bean 一般与 @Configuration 同时出现,封装 ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition 时,配置类被看作工厂类,@Bean 方法被看作工厂方法,所以实例化时,会调用 AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod。
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
// ConstructorResolver
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
// 获取工厂 beanName
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw ...
}
// 获取 factoryBean
// 如果工厂 bean 未实例化,先对工厂 bean 进行实例化
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
this.beanFactory.registerDependentBean(factoryBeanName, beanName);
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// static 方法
if (!mbd.hasBeanClass()) {
throw ...
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached factory method...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
}
}
if (factoryMethodToUse == null || argsToUse == null) {
// 针对 Cglib 代理类,获取的是其父类,即目标类
// com.icheetor.annotation.service.impl.UserServiceImpl
factoryClass = ClassUtils.getUserClass(factoryClass);
List<Method> candidates = null;
if (mbd.isFactoryMethodUnique) {
if (factoryMethodToUse == null) {
// 获取工厂方法
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) {
candidates = new ArrayList<>();
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
for (Method candidate : rawCandidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.get(0);
// 无参情况,即不依赖其它 bean
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// 实例化
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// 候选者多于一个,先排序,根据方法修饰符和参数个数排序
if (candidates.size() > 1) {
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// constructor-arg
// ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition 类型的 BeanDefinition 实际上不存在
if (mbd.hasConstructorArgumentValues()) {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
Deque<UnsatisfiedDependencyException> causes = null;
for (Method candidate : candidates) {
int parameterCount = candidate.getParameterCount();
if (parameterCount >= minNrOfArgs) {
ArgumentsHolder argsHolder;
// 获取参数类型
Class<?>[] paramTypes = candidate.getParameterTypes();
if (explicitArgs != null) {
// 存在明确参数,给定参数长度必须和参数类型长度一致
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// 解析构造参数
try {
// 解析参数名称
String[] paramNames = null;
// DefaultParameterNameDiscoverer
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
// 解析依赖参数 bean
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
}
catch (UnsatisfiedDependencyException ex) {
// 异常入列
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
// 类型差异权重
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 赋值
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// Find out about ambiguity: In case of the same type difference weight
// for methods with the same number of parameters, collect such candidates
// and eventually raise an ambiguity exception.
// However, only perform that check in non-lenient constructor resolution mode,
// and explicitly ignore overridden methods (with the same parameter signature).
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
if (factoryMethodToUse == null || argsToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
List<String> argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else if (resolvedValues != null) {
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
argTypes.add(argType);
}
}
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
// BeanCreationException
throw ...
}
// 返回值类型不能为 void,@Bean 方法返回的是实例 bean
else if (void.class == factoryMethodToUse.getReturnType()) {
throw ...
}
// 模糊的工厂方法
else if (ambiguousFactoryMethods != null) {
throw ...
}
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
// instantiate 方法进行实例化
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
代码比较长,核心逻辑如下:
- 确定工厂 bean,未实例化,先对工厂 bean 进行实例化
- 确定待使用的工厂方法,作为 candidates
- 如果 candidates 只有一个,并且工厂方法没有参数,即不依赖其它 bean,直接进行实例化,并将返回的半成品对象设置给 bw
- 当 candidates 有多个,或者只有一个,但工厂方法存在参数时,遍历 candidates,解析依赖的参数 bean,最终确定出要使用的工厂方法以及依赖的其它 bean 封装成的参数 argsToUse
- 实例化,并将返回的半成品对象设置给 bw
此处有一点需要注意,就是 @Bean 修饰的方法,方法参数表示对其它 bean 的依赖,相当于 xml 中定义的 ref=“someBean”,所以参数类型如果是基本类型会抛出异常。
下面来看下对依赖的参数 bean 的解析。
方法依赖参数解析 createArgumentArray
顾名思义,创建参数数组。
// ConstructorResolver
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
if (valueHolder.isConverted()) {
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException...
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
}
args.arguments[paramIndex] = convertedValue;
args.rawArguments[paramIndex] = originalValue;
}
else {
// 封装 MethodParameter
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// true
if (!autowiring) {
throw new UnsatisfiedDependencyException...
}
try {
// 解决指定参数自动注入的模板方法
// 解析完得到依赖的 bean 实例对象
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException...
}
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
}
return args;
}
我们知道,@Bean 修饰的方法在配置类解析时都被处理成了 ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition,而这个 BeanDefinition 是不存在 constructor-arg 的,所以方法中 resolvedValues 为 null,将 executable,此处即 Method,封装成 MethodParameter。接着调用 resolveAutowiredArgument。
@Nullable
protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
// 获取参数类型
Class<?> paramType = param.getParameterType();
if (InjectionPoint.class.isAssignableFrom(paramType)) {
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
throw ...
}
return injectionPoint;
}
try {
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
catch (NoUniqueBeanDefinitionException ex) {
throw ex;
}
catch (NoSuchBeanDefinitionException ex) {
// fallback 取决于 instantiateUsingFactoryMethod 中工厂方法 candidates 数量是否等于 1
if (fallback) {
if (paramType.isArray()) {
return Array.newInstance(paramType.getComponentType(), 0);
}
else if (CollectionFactory.isApproximableCollectionType(paramType)) {
return CollectionFactory.createCollection(paramType, 0);
}
else if (CollectionFactory.isApproximableMapType(paramType)) {
return CollectionFactory.createMap(paramType, 0);
}
}
throw ex;
}
}
通过 beanFactory 完成对依赖的解析。具体可参考 spring 注解模式下对依赖的解析。
得到 args 之后,通过 ConstructorResolver#instantiate 进行实例化。
// ConstructorResolver
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
if (System.getSecurityManager() != null) {
...
}
else {
// 获取实例化策略,针对 beanName 进行实例化
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
}
catch (Throwable ex) {
throw new BeanCreationException...
}
}
获取 beanFactory 中配置的实例化策略,进行实例化,与 spring 中常规 bean 的实例化完成了统一。
// SimpleInstantiationStrategy
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
...
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}
// ThreadLocal
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
// 工厂方法调用,如果 factoryBean 是 Cglib 增强过的,会调入对应 intercept 方法,例如 BeanMethodInterceptor
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
catch (IllegalArgumentException ex) {
throw ...
}
catch (IllegalAccessException ex) {
throw ...
}
catch (InvocationTargetException ex) {
throw ...
}
}
通过工厂方法,反射完成对象的创建。此处有一点要注意,就是配置类如果是增强过的,即配置类是 Cglib 创建的代理对象,调用 invoke 方法时,会调入对应 intercept 方法,例如 BeanMethodInterceptor。
// org.springframework.context.annotation.ConfigurationClassEnhancer.BeanMethodInterceptor
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// 获取 beanFactory
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// Determine whether this bean is a scoped-proxy
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
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.
// 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)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Scoped proxy factory beans are a special case and should not be further proxied
}
else {
// It is a candidate FactoryBean - go ahead with enhancement
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
if (logger.isInfoEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
...
}
// MethodProxy 调用
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
// MethodProxy
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);
}
catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
通过 cglibMethodProxy 去执行,其实是进行了一个二次代理,这样完成之后,直接转化为对父类方法的调用,减少了反射调用的开销。
举个例子:
// 二次代理后生成
// var1 fci.i2 6
// var2 obj 一次代理后创建的对象
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
3180d523 var10000 = (3180d523)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
...
case 6:
return var10000.CGLIB$initSchool$1();
...
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
// 配置类第一次被代理时生成这个方法
final School CGLIB$initSchool$1() {
return super.initSchool();
}
@Bean
public School initSchool() {
return new School("清华大学");
}
从网上的相关介绍来看,这种方式虽然生成了二次代理,然后才完成了方法调用,但是性能上还是要优于直接的反射调用的。自 spring 5.2 之后,@Configuration 中新增了 proxyBeanMethods 属性,用来控制是否对配置类进行代理,也算是性能上的一种优化。
创建完成之后,将实例化对象填充进 bw,之后的处理就和 spring 中普通实例对象的处理一致了。
写在最后
顺便说下,注解模式本身是对 XML 模式的一种补充,采用注解模式,配置简单直观,但每次修改都需重新编译代码,而 XML 模式,修改 XML 后,无需重新编译代码,重新启动项目即可。并且,当注解和 XML 共同使用时,XML 的优先级是要高于注解的,这样如果需要修改,直接修改 XML 重启项目即可。