beanFactory接口继承关系
spring IOC部分的接口、抽象类继承关系非常复杂。想要读懂spring源码,首先要理清IOC部分的类继承关系。理解每个接口的作用。
如上图所示,BeanFactory类如其名,是真正实现了IOC容器的基类接口。它提供了bean容器的基本操作。如getBean()方法,containsBean()方法判断是否存在该bean,isSingleton()和isPrototype()方法分别判断bean的作用范围是容器中单例还是prototype,prototype这里运用了原型设计模式,即通过clone创建多个对象。除此之外,还包括isTypeMatch()方法用于判断bean的类型是否匹配,getType()方法获取bean的类型,getAliases()方法获取bean的别名。
有三个子接口继承了beanFactory。分别是:
- HierarchicalBeanFactory:类似一个中间接口,提供了getParentBeanFactory()方法。继承它的configurableBeanFactory接口负责对beanFactory的配置功能,如加载后置处理器(BeanPostProcessor)
- ListableBeanFactory:最常用的beanFactory,细化了一些beanFactory的操作,比如提供了getBeanDefinationNames()方法,封装了一些bean的高级操作。
- AutowireCapableBeanFactory:和上面一样,也是在beanFactory之上提供了一些对bean的操作(具体是干嘛的我也不知道)。
这个接口系统以beanFactory和ApplicationContext为核心,而中间部分的接口关系对开发者并不友好,beanFactory提供了基础的容器功能,而ApplicationContext是spring面向开发者开放的真正“接口”,它在继承了三大BeanFactory接口之上,又继承了MessageSource(国际化相关接口)、ResourceLoader接口(资源读取,spring中的配置文件是以Resource形式存在的)以及ApplicationEventPublisher接口(事件处理),这些接口给予ApplicationContext更高级的特性。
如果不使用封装好的ApplicationContext,而使用ConfigurableBeanFactory下的DefaultListableBeanFactory实现类,需要我们手动加载配置文件并读取,过程较为繁琐,增加了一些灵活性(比如可以手动注册自定义的bean后置处理器),
//加载配置文件并启动容器
Resource resource = new ClassPathResource("spring-beans.xml");
//DefaultListableBeanFactory实现了configurationBeanFactory和ListableBeanFactory接口,是IOC的一个重要实现,ApplicationContext也是基于它
BeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) bf);
reader.loadBeanDefinitions(resource);
//加载beanPostProcessor 后置bean处理器
((ConfigurableListableBeanFactory) bf).addBeanPostProcessor(new MyBeanPostProcessor());
((ConfigurableListableBeanFactory) bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
//从beanFactory中获取bean时对bean进行实例化。而是用applicationContext则是在容器启动时初始化所有bean
Car car = (Car) bf.getBean("car");
car.setColor("blue");
//从容器缓存池中获取bean
Car car1 = (Car) bf.getBean("car");
System.out.println("是否为统一引用?" + (car == car1));
//关闭容器
((ConfigurableListableBeanFactory) bf).destroySingletons();
但如果使用ApplicationContext,两行代码就完成了。
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring-beans.xml");
ctx.getBean("car");
常用ClassPathXmlApplicationContext从classpath中读取配置文件,也可以使用FileSystemXmlApplicationContext从文件系统中读取,除此之外,spring也提供了在web环境下的WebApplicationContext,它继承了ApplicationContext,具备了ApplicationContext的所有功能。
IOC过程
IOC初始化:
1.资源位置解析(定位)
2.资源文件载入、解析
3.注册资源文件
在spring中,这三个操作是独立的,并不交给ApplicationContext处理,
我们从FileSystemXmlApplicationContext入手,看看IOC是怎么实现的,首先进入FileSystemXmlApplicationContext加载配置文件的重载方法。
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if (refresh) {
this.refresh();
}
}
这部分和ClappPathXmlApplicationContext一摸一样,
refresh是Bean初始化的核心方法,控制其初始化过程。
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
//加锁
synchronized(this.startupShutdownMonitor) {
//记录startTime,打开日志debug,初始化属性池
this.prepareRefresh();
//确保有且只有一个beanFactory初始化(默认DefaultListableBeanFactory)
ConfigurableListableBeanFactory beanFactory =
this.obtainFreshBeanFactory();
//为beanFactory注入配置信息
this.prepareBeanFactory(beanFactory);
try {
//初始化bean后置处理器
this.postProcessBeanFactory(beanFactory);
//调用
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册
this.registerBeanPostProcessors(beanFactory);
//初始化国际化支持
this.initMessageSource();
//初始化事件处理
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var5) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
this.destroyBeans();
this.cancelRefresh(var5);
throw var5;
}
}
}
//上图中obtainFreshBeanFactory()方法调用的refreshBeanFactory()方法
protected final void refreshBeanFactory() throws BeansException {
//如果已存在beanFactory,则销毁,重建
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
//以DefaultListableBeanFactory创建默认的beanFactory
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
//设置唯一ID
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
//加载beanDefinitions
this.loadBeanDefinitions(beanFactory);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
//上图中loadBeanDefinitions()方法调用AbstractXmlApplicationContext实现类的方法
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
}
//ApplicationContext并不处理配置文件的解析,加载。而是交给AbstractBeanDefinitionReader处理。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = this.getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//加载配置文件并计数
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
//AbstractBeanDefinitionReader类处理配置文件
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int counter = 0;
String[] var3 = locations;
int var4 = locations.length;
for(int var5 = 0; var5 < var4; ++var5) {
String location = var3[var5];
counter += this.loadBeanDefinitions(location);
}
return counter;
}
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
//获取资源加载器
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
} else {
int loadCount;
//如果不是ResourcePatternResolver,使用默认resourceLoader定位资源
//ResourcePatternResolver是专用来解析ant风格路径的
//比如* ** ?:在资源加载中分别代表本目录,多级目录,任意字符
if (!(resourceLoader instanceof ResourcePatternResolver)) {
Resource resource = resourceLoader.getResource(location);
loadCount = this.loadBeanDefinitions((Resource)resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
} else {
try {
//使用ResourcePatternResolver定位资源
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
loadCount = this.loadBeanDefinitions(resources);
//actualResources用于保存实际的resource
if (actualResources != null) {
Resource[] var6 = resources;
int var7 = resources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource resource = var6[var8];
actualResources.add(resource);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
} catch (IOException var10) {
throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
}
}
}
}
//默认的资源加载器
//判断 文件系统路径 classpath路径 url风格 做相应处理
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
if (location.startsWith("/")) {
return this.getResourceByPath(location);
} else if (location.startsWith("classpath:")) {
return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
} else {
try {
URL url = new URL(location);
return new UrlResource(url);
} catch (MalformedURLException var3) {
//做了异常处理,如果既不是classoath又不是url资源
return this.getResourceByPath(location);
}
}
}
//未完待续。。。
getBean()
先从bean的生命周期入手,分析一下getBean()方法的调用过程。
从图中可以看到,bean的生命周期经过四部分的方法处理
* 1.bean本身的方法,构造方法,getter/setter,自定义的init-method ,destroy-method(需在xml文件中配置)
* 2.bean实现生命周期接口的方法,如:
* BeanFactoryAware(setBeanFactory方法)
* BeanNameAware(setBeanName方法)
* InitializingBean(afterPropertiesSet方法,bean实例化前调用)
* DisposableBean(destroy方法,bean销毁时调用)
* 3.容器级声明周期方法:
* InstantiationAwareBeanPostAware接口的postProcessBeforeInstantiation方法(实例化前调用)、postProcessAfterInstantiation方法(实例化后调用)、postProcessPropertyValues方法(注入属性值时调用)
* BeanPostProcessor接口的postProcessBeforeInitialization方法、postProcessAfterInitialization方法。
以上生命周期的执行过程如图,但以上的接口与bean生命周期耦合的过于严重,除非开发spring的bean插件,否则完全可以抛弃除了BeanPostProcessor接口的其他生命周期接口。