死磕源码系列【ConfigurationWarningsApplicationContextInitializer源码解析】

ConfigurationWarningsApplicationContextInitializer是ApplicationContextInitializer初始化器接口的实现类,用作报告常见错误配置的警告(通过分析源码实际情况是如果系统配置包扫描(@ComponentScan)到了org或者org.springframework包就会发出警告并停止系统启动)

ConfigurationWarningsApplicationContextInitializer初始化器源码:
public class ConfigurationWarningsApplicationContextInitializer
		implements ApplicationContextInitializer<ConfigurableApplicationContext> {

	private static final Log logger = LogFactory.getLog(ConfigurationWarningsApplicationContextInitializer.class);
	//初始化方法会在容器启动时调用,并将ConfigurationWarningsPostProcessor后置处理器注入到应用上下文中
	@Override
	public void initialize(ConfigurableApplicationContext context) {
		context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
	}

	/**
	 * 返回有问题的扫描包(@ComponentScan)Check对象
	 * @return the checks to apply
	 */
	protected Check[] getChecks() {
		return new Check[] { new ComponentScanPackageCheck() };
	}
	}
ComponentScanPackageCheck是ConfigurationWarningsApplicationContextInitializer的一个内部类,源码分析
/**
	 * 可以应用的单一检查
	 */
	@FunctionalInterface
	protected interface Check {

		/**
		 * 返回检查结果,如果检查失败,则返回警告,如果没有问题,则返回null
		 * @param registry the {@link BeanDefinitionRegistry}
		 * @return a warning message or {@code null}
		 */
		String getWarning(BeanDefinitionRegistry registry);

	}

	/**
	 * 检查@ComponentScan注解扫描有问题的包
	 */
	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);
		}
		//检查@ComponentScan注解扫描的包是否有问题,如果有,则返回警告,否则返回null
		@Override
		public String getWarning(BeanDefinitionRegistry registry) {
      //获取@ComponentScan注解扫描的包集合
			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, ", ") + ".";
		}
		//获取@ComponentScan注解扫描的包
		protected Set<String> getComponentScanningPackages(BeanDefinitionRegistry registry) {
			Set<String> packages = new LinkedHashSet<>();
      //获取容器中所有bean定义名称
			String[] names = registry.getBeanDefinitionNames();
			for (String name : names) {
        //获取name对应的bean定义对象
				BeanDefinition definition = registry.getBeanDefinition(name);
				if (definition instanceof AnnotatedBeanDefinition) {
					AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition) definition;
					addComponentScanningPackages(packages, annotatedDefinition.getMetadata());
				}
			}
			return packages;
		}
		//将bean实例上注解@ComponentScan扫描包
		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[] values) {
			if (values != null) {
				Collections.addAll(packages, values);
			}
		}

		private void addClasses(Set<String> packages, String[] values) {
			if (values != null) {
				for (String value : values) {
					packages.add(ClassUtils.getPackageName(value));
				}
			}
		}
		//获取有问题的扫描包集合,即包名是:org或org.springframework
		private List<String> getProblematicPackages(Set<String> scannedPackages) {
			List<String> problematicPackages = new ArrayList<>();
			for (String scannedPackage : scannedPackages) {
        //判定包名是否有问题,即包名是:org或org.springframework
				if (isProblematicPackage(scannedPackage)) {
					problematicPackages.add(getDisplayName(scannedPackage));
				}
			}
			return problematicPackages;
		}
		//判定包名是否有问题,即包名是:org或org.springframework
		private boolean isProblematicPackage(String scannedPackage) {
			if (scannedPackage == null || scannedPackage.isEmpty()) {
				return true;
			}
			return PROBLEM_PACKAGES.contains(scannedPackage);
		}

		private String getDisplayName(String scannedPackage) {
			if (scannedPackage == null || scannedPackage.isEmpty()) {
				return "the default package";
			}
			return "'" + scannedPackage + "'";
		}

	}


GitHub地址:https://github.com/mingyang66/spring-parent

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值