ConfigurationWarningsApplicationContextInitializer Class — spring-boot Architecture
Architecture documentation for the ConfigurationWarningsApplicationContextInitializer class in ConfigurationWarningsApplicationContextInitializer.java from the spring-boot codebase.
Entity Profile
Source Code
core/spring-boot/src/main/java/org/springframework/boot/context/ConfigurationWarningsApplicationContextInitializer.java lines 53–216
public class ConfigurationWarningsApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private static final Log logger = LogFactory.getLog(ConfigurationWarningsApplicationContextInitializer.class);
@Override
public void initialize(ConfigurableApplicationContext context) {
context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
}
/**
* Returns the checks that should be applied.
* @return the checks to apply
*/
protected Check[] getChecks() {
return new Check[] { new ComponentScanPackageCheck() };
}
/**
* {@link BeanDefinitionRegistryPostProcessor} to report warnings.
*/
protected static final class ConfigurationWarningsPostProcessor
implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {
private final Check[] checks;
public ConfigurationWarningsPostProcessor(Check[] checks) {
this.checks = checks;
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE - 1;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
for (Check check : this.checks) {
String message = check.getWarning(registry);
if (StringUtils.hasLength(message)) {
warn(message);
}
}
}
private void warn(String message) {
if (logger.isWarnEnabled()) {
logger.warn(String.format("%n%n** WARNING ** : %s%n%n", message));
}
}
}
/**
* A single check that can be applied.
*/
@FunctionalInterface
protected interface Check {
/**
* Returns a warning if the check fails or {@code null} if there are no problems.
* @param registry the {@link BeanDefinitionRegistry}
* @return a warning message or {@code null}
*/
@Nullable String getWarning(BeanDefinitionRegistry registry);
}
/**
* {@link Check} for {@code @ComponentScan} on problematic package.
*/
protected static class ComponentScanPackageCheck implements Check {
private static final Set<String> PROBLEM_PACKAGES;
static {
Set<String> packages = new HashSet<>();
packages.add("org.springframework");
packages.add("org");
PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
}
@Override
public @Nullable String getWarning(BeanDefinitionRegistry registry) {
Set<String> scannedPackages = getComponentScanningPackages(registry);
List<String> problematicPackages = getProblematicPackages(scannedPackages);
if (problematicPackages.isEmpty()) {
return null;
}
return "Your ApplicationContext is unlikely to start due to a @ComponentScan of "
+ StringUtils.collectionToDelimitedString(problematicPackages, ", ") + ".";
}
protected Set<String> getComponentScanningPackages(BeanDefinitionRegistry registry) {
Set<String> packages = new LinkedHashSet<>();
String[] names = registry.getBeanDefinitionNames();
for (String name : names) {
BeanDefinition definition = registry.getBeanDefinition(name);
if (definition instanceof AnnotatedBeanDefinition annotatedDefinition) {
addComponentScanningPackages(packages, annotatedDefinition.getMetadata());
}
}
return packages;
}
private void addComponentScanningPackages(Set<String> packages, AnnotationMetadata metadata) {
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(ComponentScan.class.getName(), true));
if (attributes != null) {
addPackages(packages, attributes.getStringArray("value"));
addPackages(packages, attributes.getStringArray("basePackages"));
addClasses(packages, attributes.getStringArray("basePackageClasses"));
if (packages.isEmpty()) {
packages.add(ClassUtils.getPackageName(metadata.getClassName()));
}
}
}
private void addPackages(Set<String> packages, String @Nullable [] values) {
if (values != null) {
Collections.addAll(packages, values);
}
}
private void addClasses(Set<String> packages, String @Nullable [] values) {
if (values != null) {
for (String value : values) {
packages.add(ClassUtils.getPackageName(value));
}
}
}
private List<String> getProblematicPackages(Set<String> scannedPackages) {
List<String> problematicPackages = new ArrayList<>();
for (String scannedPackage : scannedPackages) {
if (isProblematicPackage(scannedPackage)) {
problematicPackages.add(getDisplayName(scannedPackage));
}
}
return problematicPackages;
}
private boolean isProblematicPackage(@Nullable String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return true;
}
return PROBLEM_PACKAGES.contains(scannedPackage);
}
private String getDisplayName(@Nullable String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return "the default package";
}
return "'" + scannedPackage + "'";
}
}
}
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free