一、准备后续执行过程用到的一些属性
1)先从ClassPathXmlApplicationContext类入口,以下面的类路径一直调用父类的构造方法以达到给后续 要用的属性赋值: 下面是在调用构造方法时,类加载的过程是从下往上
- ClassPathXmlApplicationContext:
- 这个类就一个属性
- private Resource[] configResources; 资源路径
- AbstractXmlApplicationContext:
- 这个类就一个属性
- private boolean validating = true; 设置xml文件的验证标志,默认是true
- AbstractRefreshableConfigApplicationContext:
- 这个类就涉及到两个属性
- private String[] configLocations; 配置文件路径
- private boolean setIdCalled = false; 不太清楚,后续再回来改
- AbstractRefreshableApplicationContext:
- 这个类主要涉及到四个属性
- private Boolean allowBeanDefinitionOverriding; 是否请允许覆盖bean定义信息
- private Boolean allowCircularReferences; 是否允许循环依赖
- private DefaultListableBeanFactory beanFactory; 大名鼎鼎bean工厂
- private final Object beanFactoryMonitor = new Object(); 对象锁
- AbstractApplicationContext:
- 这个类中涉及到的属性比较多,代表性的有
- private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>(); bean工厂后置处理器容器
- private ConfigurableEnvironment environment; 上下文环境
- private ResourcePatternResolver resourcePatternResolver; 创建一个资源模式解 析器PathMatchingResourcePatternResolver(其实就是用来解析xml配置文 件)
2)设置AbstractRefreshableConfigApplicationContext类中的属性configLocations(外面传进来的配 置文件路径)
3)上面做完后,接着还要做一些准备工作,其中最重要的一点就是initPropertySources();这个方法在 spring源码里面是空的,留给我们扩展用的,我们可以继承ClassPathXmlApplicationContext类来重 定这个方法, 我们可以在重写的方法里面做的事情:在上下文环境中初始化任何占位符属性来源。
当然还有些其他准备如:事件容器、应用程序监听器容器等准备工作
二、创建bean工厂并加载xml配置文件生成BeanDefinition对象添加进bean工厂
1)主要分下面四大步执行
// 创建DefaultListableBeanFactory对象
- DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为了序列化指定id,可以从id反序列化BeanFactory对象
- beanFactory.setSerializationId(getId());
// 定制BeanFactory,设置相关属性,包括是否允许覆盖同名称的对象以及循环依赖,
// 和上面一样,我们也可以来重写这个方法
- customizeBeanFactory(beanFactory);
// 初始化documentReader,并进行xml文件读取及解析,这步是灵魂,后续要多次翻看
// 这里面还可以实现自定义标签:
- loadBeanDefinitions(beanFactory);
实现要有下面几样东西
1、命令空间处理类:
- 继承NamespaceHandlerSupport类重写init()方法,可参考ContextNamespaceHandler这 个类
2、标签解析类,
- 继承AbstractSingleBeanDefinitionParser类重写getBeanClass和doParse这两个方 法,可参考PropertyPlaceholderDefinitionParser类
3、在resources目录下建个META-INF目录,建下面这两个文件
- spring.handlers:
配置例如: http\://www.xiong.com/schema/user=com.xiong.selftag.
UserNamespaceHandler
- spring.schemas:
配置例如:
http\://www.xiong.com/schema/user/fan.xsd=META-INF/fan.xsd
4、 在创建个fan.sxd文件
三、bean工厂的一些准备工作
// 设置beanFactory的表达式语言处理器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置beanFactory的表达式语言处理器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性值编辑设置管理的一个工具类
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 添加beanPostProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 设置要忽略自动装配的接口,这些接口的实现是由容器通过set方法进行注入的
// 所以在使用autowire进行注入的时候需要将这些接口进行忽略
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现,那么就使用指定的对象进行注入
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
下面来说上面第6行如何实现像它一样扩展一个自定义的属性值编辑器:
核心:首先spring中给我们提供了一个CustomEditorConfigurer配置类,这个配置类是实现了BeanFactoryPostProcessor接口,意味着实现类就是一个后置处理器了,也就是说,spring在执行过程会调用refresh方法中的invokeBeanFactoryPostProcessors方法,而这个方法中会对所有实现了BeanFactoryPostProcessor接口的类提前创建出一个bean实例出来,然后依次调用每个实例的postProcessBeanFactory方法来执行我们自己要扩展的一些逻辑处理
其次:CustomEditorConfigurer这个配置类中最重要的两个属性propertyEditorRegistrars、customEditors:
propertyEditorRegistrars:可以用来存储属性值编辑器注册类,这个注册类首先要实现PropertyEditorRegistrar接口,进而实现方法registerCustomEditors,在这个方法中可以把实现接口PropertyEditor(里面有个setAsText方法)的一个类的实例对象添加到后面需要用的一个map中去
customEditors:这个属性就直接存储属性值编辑器了,这个可以直接在CustomEditorConfigurer类bean创建时会给这个属性赋值一个编辑器了,后续会把这个里面编辑器添加到一个map中去以供后面使用
bean工厂后置处理器的执行操作
会执行这个方法invokeBeanFactoryPostProcessors(beanFactory);
这个方法里面的代码不算复杂:大致记住两个接口就能理解了:
1、BeanDefinitionRegistryPostProcessor: 这个接口是下面接口的子接口:其主要作用是beanDefinition进行增删改, 同时也可以实现下面接口的功能
2、BeanFactoryPostProcessor:这个接口主要作用是对bean工厂的一些属性进行增删改
ConfigurationClassPostProcessor类分析
这个类主要作用是完成注解形式的生成bean定义信息
注册BeanPostProcessor类型的所有bean后置处理器