spring源码分析01
父子容器
mvc开发中,父子容器:
web.xml文件中,会配置DispatherServlet,这个servlet中封装了spring工厂,这个是child工厂;
另一个是 ContextLoaderLister 创建的工厂,这个是root工厂
父子容器问题:controller获取service时候,虽然配置了事务,但是事务没有生效。
原因:事务是在父工厂配置的,父工厂创建了service,添加了事务;子工厂创建的service没有事务,controller是dispatherservlet这个子工厂创建的,自然没有事务。
解决方案:子工厂不创建service,去调用父工厂的service。
springboot没有父子容器问题,因为tomcat是它内嵌的,不需要外部激活来创建。==>
另一个好处,以jar包启动tomcat的进程==>单体应用,微服务拆分的优点
工厂:容器,创建、储存功能
ApplicationContext spring编程门面,集合了其他的工厂能力,功能最多。BeanFactory是spring最核心最底层的工厂。
DefaultListableBeanFactory,偏框架底层的工厂
spring编程中严格遵守了`类型单一原则`,因此工厂继承体系特别复杂
spring工厂分类
工厂的分类:
BeanFactory:spring的底层工厂,提供了进行访问和操作的最基本功能:存,取
- HierarchicalBeanFactory 父子容器的能力(分级豆工厂,继承)
- ConfigurableBeanFactory:配置工厂:单实例,多实例,类型转换器,后置处理器
- AutowireCapableBeanFactory:自动注入工厂:自动注入,生命周期
- ListableBeanFactory:实现了beanFactory定义的绝大多数接口,功能强大;获取相关的配置信息,
- DefaultListableBeanFactory:ListAbleBeanFactory接口的实现类
- XmlBeanFactory:需要使用到此类解析xml配置文件,创建对应对象
1.学习目标
工厂使用方式:
BeanFactory beanFactory = new XmlBeanFactory(Resource-->xml);
ioc工厂核心内容:
beanFactory.getBean("")-->target
BeanFactory怎么创建工厂,获取对象?
- 定义applicationContext.xml的配置文件
- 工厂如何解析xml
- 解析默认标签
- 解析自定义标签
- 封装为 beanDefinition
- 存储为 BeanDefinition
- 对象的创建(BeanFactory)
- 完整对象
引申学习目标:
1.怎么读取配置文件,获得IO资源:通过resource接口
2.读取配置文件后,如何在spring中以对象的形式进行封装
3.根据配置信息生成对象:循环依赖
4.所创建对象的生命周期:注入
1.1Resource接口读取配置文件
Resource(资源)
- ClassPathResource
- ServletContextResource
实现类不重要,目的是通过该接口的某个实现类获得 InputStream ,从而进行解析(类似mybatis,第一步读取配置文件),最终在JVM中以对象的形式进行保存。保存的对象类型为:BeanDefinition(Interface)。
xml解析:mybatis使用xpath框架,spring使用sax框架
1.2创建BeanFactory工厂
1.2.1XmlBeanFactory内部实现:
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
1.2.2BeanDefiniton实现树:
BeanDefinition(I)
- AbstractBeanDefinition()
- GenericBeanDefinition(最为广泛,这个可以实例化)
XmlBeanDefinitonReader
XmlBeanDefinitonReader是XmlBeanFactory的成员属性
new XmlBeanDefinitonReader(BeanFactory).loadBeanDefinitions(Resource)
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
Product product = (Product) beanFactory.getBean("p");
System.out.println("product = " + product);
DefaultListableBeanFactory beanFactory1 = new DefaultListableBeanFactory();
Resource resource = new ClassPathResource("applicationContext.xml");
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory1);
xmlBeanDefinitionReader.loadBeanDefinitions(resource);
Object product1 = beanFactory1.getBean("p");
System.out.println("product1 = " + product1);
正常编程中,我们使用:
ApplicationContect context = new ClassPathXmlApplicationContext("classpath:application.xml")
这个工厂进行开发,这也侧面证明了ApplicationContext工厂和XmlBeanFactory是较为高级的工厂,因为不需要显示调用Resource接口的实现
1.2.3xml文件的解析
xml解析方式
mybatis xml解析 xpath
spring xml解析 sax
spring允许同时存在多个工厂
new XmlBeanFactory()
获取inputStream输入流
doLoadBeanDefinitions
doLoadDocument/registerBeanDefinitions
parseBeanDefinitions
parseDefaultElement
processBeanDefinition
registerBeanDefinition
registerBeanDefinition