Support load-time weaving for @Component classes again
Since Spring Framework 5.2, the LoadTimeWeaver no longer weaves bean
classes annotated with @Component. This is a regression caused by the
changes in 40c62139ae, stemming from the fact that any class annotated
or meta-annotated with @Component is considered to be a candidate
configuration class in 'configuration lite' mode (i.e., a class without
the @Configuration annotation and without any @Bean methods) and
therefore now has its class eagerly loaded. This results in the class
being loaded before the LoadTimeWeaver has a chance to weave it.
This commit fixes this regression by explicitly avoiding eager class
loading for any 'lite' @Configuration or @Component class without @Bean
methods.
Closes gh-26199
This commit is contained in:
@@ -81,6 +81,7 @@ import org.springframework.util.ClassUtils;
|
|||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
|
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
|
||||||
@@ -376,21 +377,30 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
|||||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||||
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
|
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
|
||||||
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
|
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
|
||||||
|
AnnotationMetadata annotationMetadata = null;
|
||||||
MethodMetadata methodMetadata = null;
|
MethodMetadata methodMetadata = null;
|
||||||
if (beanDef instanceof AnnotatedBeanDefinition) {
|
if (beanDef instanceof AnnotatedBeanDefinition) {
|
||||||
methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
|
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
|
||||||
|
annotationMetadata = annotatedBeanDefinition.getMetadata();
|
||||||
|
methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
|
||||||
}
|
}
|
||||||
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
|
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
|
||||||
// Configuration class (full or lite) or a configuration-derived @Bean method
|
// Configuration class (full or lite) or a configuration-derived @Bean method
|
||||||
// -> resolve bean class at this point...
|
// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
|
||||||
|
// or component class without @Bean methods.
|
||||||
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
|
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
|
||||||
if (!abd.hasBeanClass()) {
|
if (!abd.hasBeanClass()) {
|
||||||
try {
|
boolean liteConfigurationCandidateWithoutBeanMethods =
|
||||||
abd.resolveBeanClass(this.beanClassLoader);
|
(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
|
||||||
}
|
annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
|
||||||
catch (Throwable ex) {
|
if (!liteConfigurationCandidateWithoutBeanMethods) {
|
||||||
throw new IllegalStateException(
|
try {
|
||||||
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
|
abd.resolveBeanClass(this.beanClassLoader);
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -46,6 +46,7 @@ import org.springframework.stereotype.Component;
|
|||||||
*
|
*
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
abstract class ConfigurationClassUtils {
|
abstract class ConfigurationClassUtils {
|
||||||
@@ -162,6 +163,10 @@ abstract class ConfigurationClassUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally, let's look for @Bean methods...
|
// Finally, let's look for @Bean methods...
|
||||||
|
return hasBeanMethods(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean hasBeanMethods(AnnotationMetadata metadata) {
|
||||||
try {
|
try {
|
||||||
return metadata.hasAnnotatedMethods(Bean.class.getName());
|
return metadata.hasAnnotatedMethods(Bean.class.getName());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user