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

﹏ヽ暗。殇╰゛Y 2022-11-21 03:34 317阅读 0赞

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

ConfigurationWarningsApplicationContextInitializer初始化器源码:
  1. public class ConfigurationWarningsApplicationContextInitializer
  2. implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  3. private static final Log logger = LogFactory.getLog(ConfigurationWarningsApplicationContextInitializer.class);
  4. //初始化方法会在容器启动时调用,并将ConfigurationWarningsPostProcessor后置处理器注入到应用上下文中
  5. @Override
  6. public void initialize(ConfigurableApplicationContext context) {
  7. context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
  8. }
  9. /** * 返回有问题的扫描包(@ComponentScan)Check对象 * @return the checks to apply */
  10. protected Check[] getChecks() {
  11. return new Check[] { new ComponentScanPackageCheck() };
  12. }
  13. }
ComponentScanPackageCheck是ConfigurationWarningsApplicationContextInitializer的一个内部类,源码分析
  1. /** * 可以应用的单一检查 */
  2. @FunctionalInterface
  3. protected interface Check {
  4. /** * 返回检查结果,如果检查失败,则返回警告,如果没有问题,则返回null * @param registry the {@link BeanDefinitionRegistry} * @return a warning message or {@code null} */
  5. String getWarning(BeanDefinitionRegistry registry);
  6. }
  7. /** * 检查@ComponentScan注解扫描有问题的包 */
  8. protected static class ComponentScanPackageCheck implements Check {
  9. private static final Set<String> PROBLEM_PACKAGES;
  10. //定义扫描有问题的包
  11. static {
  12. Set<String> packages = new HashSet<>();
  13. packages.add("org.springframework");
  14. packages.add("org");
  15. PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
  16. }
  17. //检查@ComponentScan注解扫描的包是否有问题,如果有,则返回警告,否则返回null
  18. @Override
  19. public String getWarning(BeanDefinitionRegistry registry) {
  20. //获取@ComponentScan注解扫描的包集合
  21. Set<String> scannedPackages = getComponentScanningPackages(registry);
  22. //获取有问题的扫描包集合
  23. List<String> problematicPackages = getProblematicPackages(scannedPackages);
  24. if (problematicPackages.isEmpty()) {
  25. return null;
  26. }
  27. return "Your ApplicationContext is unlikely to start due to a @ComponentScan of "
  28. + StringUtils.collectionToDelimitedString(problematicPackages, ", ") + ".";
  29. }
  30. //获取@ComponentScan注解扫描的包
  31. protected Set<String> getComponentScanningPackages(BeanDefinitionRegistry registry) {
  32. Set<String> packages = new LinkedHashSet<>();
  33. //获取容器中所有bean定义名称
  34. String[] names = registry.getBeanDefinitionNames();
  35. for (String name : names) {
  36. //获取name对应的bean定义对象
  37. BeanDefinition definition = registry.getBeanDefinition(name);
  38. if (definition instanceof AnnotatedBeanDefinition) {
  39. AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition) definition;
  40. addComponentScanningPackages(packages, annotatedDefinition.getMetadata());
  41. }
  42. }
  43. return packages;
  44. }
  45. //将bean实例上注解@ComponentScan扫描包
  46. private void addComponentScanningPackages(Set<String> packages, AnnotationMetadata metadata) {
  47. AnnotationAttributes attributes = AnnotationAttributes
  48. .fromMap(metadata.getAnnotationAttributes(ComponentScan.class.getName(), true));
  49. if (attributes != null) {
  50. addPackages(packages, attributes.getStringArray("value"));
  51. addPackages(packages, attributes.getStringArray("basePackages"));
  52. addClasses(packages, attributes.getStringArray("basePackageClasses"));
  53. if (packages.isEmpty()) {
  54. packages.add(ClassUtils.getPackageName(metadata.getClassName()));
  55. }
  56. }
  57. }
  58. private void addPackages(Set<String> packages, String[] values) {
  59. if (values != null) {
  60. Collections.addAll(packages, values);
  61. }
  62. }
  63. private void addClasses(Set<String> packages, String[] values) {
  64. if (values != null) {
  65. for (String value : values) {
  66. packages.add(ClassUtils.getPackageName(value));
  67. }
  68. }
  69. }
  70. //获取有问题的扫描包集合,即包名是:org或org.springframework
  71. private List<String> getProblematicPackages(Set<String> scannedPackages) {
  72. List<String> problematicPackages = new ArrayList<>();
  73. for (String scannedPackage : scannedPackages) {
  74. //判定包名是否有问题,即包名是:org或org.springframework
  75. if (isProblematicPackage(scannedPackage)) {
  76. problematicPackages.add(getDisplayName(scannedPackage));
  77. }
  78. }
  79. return problematicPackages;
  80. }
  81. //判定包名是否有问题,即包名是:org或org.springframework
  82. private boolean isProblematicPackage(String scannedPackage) {
  83. if (scannedPackage == null || scannedPackage.isEmpty()) {
  84. return true;
  85. }
  86. return PROBLEM_PACKAGES.contains(scannedPackage);
  87. }
  88. private String getDisplayName(String scannedPackage) {
  89. if (scannedPackage == null || scannedPackage.isEmpty()) {
  90. return "the default package";
  91. }
  92. return "'" + scannedPackage + "'";
  93. }
  94. }

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

发表评论

表情:
评论列表 (有 0 条评论,317人围观)

还没有评论,来说两句吧...

相关阅读