一、准备后续执行过程用到的一些属性

  1. 1)先从ClassPathXmlApplicationContext类入口,以下面的类路径一直调用父类的构造方法以达到给后续 要用的属性赋值: 下面是在调用构造方法时,类加载的过程是从下往上
  2. - ClassPathXmlApplicationContext:
  3. - 这个类就一个属性
  4. - private Resource[] configResources; 资源路径
  5. - AbstractXmlApplicationContext:
  6. - 这个类就一个属性
  7. - private boolean validating = true; 设置xml文件的验证标志,默认是true
  8. - AbstractRefreshableConfigApplicationContext:
  9. - 这个类就涉及到两个属性
  10. - private String[] configLocations; 配置文件路径
  11. - private boolean setIdCalled = false; 不太清楚,后续再回来改
  12. - AbstractRefreshableApplicationContext:
  13. - 这个类主要涉及到四个属性
  14. - private Boolean allowBeanDefinitionOverriding; 是否请允许覆盖bean定义信息
  15. - private Boolean allowCircularReferences; 是否允许循环依赖
  16. - private DefaultListableBeanFactory beanFactory; 大名鼎鼎bean工厂
  17. - private final Object beanFactoryMonitor = new Object(); 对象锁
  18. - AbstractApplicationContext:
  19. - 这个类中涉及到的属性比较多,代表性的有
  20. - private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>(); bean工厂后置处理器容器
  21. - private ConfigurableEnvironment environment; 上下文环境
  22. - private ResourcePatternResolver resourcePatternResolver; 创建一个资源模式解 析器PathMatchingResourcePatternResolver(其实就是用来解析xml配置文 件)
  23. 2)设置AbstractRefreshableConfigApplicationContext类中的属性configLocations(外面传进来的配 置文件路径)
  24. 3)上面做完后,接着还要做一些准备工作,其中最重要的一点就是initPropertySources();这个方法在 spring源码里面是空的,留给我们扩展用的,我们可以继承ClassPathXmlApplicationContext类来重 定这个方法, 我们可以在重写的方法里面做的事情:在上下文环境中初始化任何占位符属性来源。
  25. 当然还有些其他准备如:事件容器、应用程序监听器容器等准备工作

二、创建bean工厂并加载xml配置文件生成BeanDefinition对象添加进bean工厂

  1. 1)主要分下面四大步执行
  2. // 创建DefaultListableBeanFactory对象
  3. - DefaultListableBeanFactory beanFactory = createBeanFactory();
  4. // 为了序列化指定id,可以从id反序列化BeanFactory对象
  5. - beanFactory.setSerializationId(getId());
  6. // 定制BeanFactory,设置相关属性,包括是否允许覆盖同名称的对象以及循环依赖,
  7. // 和上面一样,我们也可以来重写这个方法
  8. - customizeBeanFactory(beanFactory);
  9. // 初始化documentReader,并进行xml文件读取及解析,这步是灵魂,后续要多次翻看
  10. // 这里面还可以实现自定义标签:
  11. - loadBeanDefinitions(beanFactory);
  12. 实现要有下面几样东西
  13. 1、命令空间处理类:
  14. - 继承NamespaceHandlerSupport类重写init()方法,可参考ContextNamespaceHandler 个类
  15. 2、标签解析类,
  16. - 继承AbstractSingleBeanDefinitionParser类重写getBeanClassdoParse这两个方 法,可参考PropertyPlaceholderDefinitionParser
  17. 3、在resources目录下建个META-INF目录,建下面这两个文件
  18. - spring.handlers
  19. 配置例如: http\://www.xiong.com/schema/user=com.xiong.selftag.
  20. UserNamespaceHandler
  21. - spring.schemas
  22. 配置例如:
  23. http\://www.xiong.com/schema/user/fan.xsd=META-INF/fan.xsd
  24. 4 在创建个fan.sxd文件

三、bean工厂的一些准备工作

  1. // 设置beanFactory的表达式语言处理器
  2. beanFactory.setBeanClassLoader(getClassLoader());
  3. // 设置beanFactory的表达式语言处理器
  4. beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  5. // 为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性值编辑设置管理的一个工具类
  6. beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
  7. // Configure the bean factory with context callbacks.
  8. // 添加beanPostProcessor
  9. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  10. // 设置要忽略自动装配的接口,这些接口的实现是由容器通过set方法进行注入的
  11. // 所以在使用autowire进行注入的时候需要将这些接口进行忽略
  12. beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
  13. beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
  14. beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  15. beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  16. beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  17. beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
  18. // BeanFactory interface not registered as resolvable type in a plain factory.
  19. // MessageSource registered (and found for autowiring) as a bean.
  20. // 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现,那么就使用指定的对象进行注入
  21. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  22. beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  23. beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  24. beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  25. // Register early post-processor for detecting inner beans as ApplicationListeners.
  26. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  27. 下面来说上面第6行如何实现像它一样扩展一个自定义的属性值编辑器:
  28. 核心:首先spring中给我们提供了一个CustomEditorConfigurer配置类,这个配置类是实现了BeanFactoryPostProcessor接口,意味着实现类就是一个后置处理器了,也就是说,spring在执行过程会调用refresh方法中的invokeBeanFactoryPostProcessors方法,而这个方法中会对所有实现了BeanFactoryPostProcessor接口的类提前创建出一个bean实例出来,然后依次调用每个实例的postProcessBeanFactory方法来执行我们自己要扩展的一些逻辑处理
  29. 其次:CustomEditorConfigurer这个配置类中最重要的两个属性propertyEditorRegistrarscustomEditors
  30. propertyEditorRegistrars:可以用来存储属性值编辑器注册类,这个注册类首先要实现PropertyEditorRegistrar接口,进而实现方法registerCustomEditors,在这个方法中可以把实现接口PropertyEditor(里面有个setAsText方法)的一个类的实例对象添加到后面需要用的一个map中去
  31. customEditors:这个属性就直接存储属性值编辑器了,这个可以直接在CustomEditorConfigurerbean创建时会给这个属性赋值一个编辑器了,后续会把这个里面编辑器添加到一个map中去以供后面使用

bean工厂后置处理器的执行操作

  1. 会执行这个方法invokeBeanFactoryPostProcessors(beanFactory);
  2. 这个方法里面的代码不算复杂:大致记住两个接口就能理解了:
  3. 1BeanDefinitionRegistryPostProcessor 这个接口是下面接口的子接口:其主要作用是beanDefinition进行增删改, 同时也可以实现下面接口的功能
  4. 2BeanFactoryPostProcessor:这个接口主要作用是对bean工厂的一些属性进行增删改

ConfigurationClassPostProcessor类分析

这个类主要作用是完成注解形式的生成bean定义信息

注册BeanPostProcessor类型的所有bean后置处理器

image.png