从上层视角入手,观测Spring容器的初始化工作。
1.初始准备
首先在Spring的源码工程里面创建一段代码,通过简单的运行代码,来追踪Spring ioc 容器的整个启动流程。
public class IocMainTest {
private static final String CONFIG_LOCATION = "applicationContext.xml";
public static void main(String[] args) {
//自定义 ioc 容器进行扩展
testDiyIoc();
}
private static void testDiyIoc() {
MyClassPathXmlApplicationContext ioc = new MyClassPathXmlApplicationContext(CONFIG_LOCATION);
Person person = ioc.getBean("person", Person.class);
System.out.println("person = " + person);
}
}
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
public MyClassPathXmlApplicationContext(String...configLocations){
super(configLocations);
}
@Override
protected void initPropertySources(){
System.out.println("这是我自己定义的ioc容器");
//getEnvironment().setRequiredProperties("ES_HOME");
}
}
程序启动之后,首先会进入自定义的ioc容器,然后通过构造器显式调用**super()**
方法来到**ClassPathXmlApplicationContext**
。
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
//调用父类的构造方法,AbstractApplicationContext
/*模板方法模式 和 钩子方法 易于扩展 开闭原则*/
super(parent);
//解析配置文件路径
setConfigLocations(configLocations);
/*refresh 是表示一个容器是否刷新过得标识符,如果容器还没有刷新过就进行容器刷新,实际上这里是一个双端检测锁*/
if (refresh) {
/*spring ioc 容器刷新方法*/
refresh();
}
}
这里面主要是做了两件事:
- 解析配置文件路径
**setConfigLocations()**
- 判断容器是否刷新过,如果尚未刷新,那么刷新ioc容器
**refresh()**
2.解析配置文件
public void setConfigLocations(@Nullable String... locations) {
/*如果location!=null 也就是说配置文件不为空,spring扫描到了配置文件,那么我们就可以以xml的形式启动spring容器*/
if (locations != null) {
/*断言:配置文件所在位置不能为空*/
Assert.noNullElements(locations, "Config locations must not be null");
/*引用*/
this.configLocations = new String[locations.length];
/*迭代解析路径*/
for (int i = 0; i < locations.length; i++) {
/*解析路径*/
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
如果我们程序是有xml的spring配置文件,那么该文件被扫描到以后,(当然可能不止一个),回去迭代解析配置文件的路径。 **resolvePath()**
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
解析给定的路径,如果有必要的话,用相应的环境属性值替换占位符,应用于配置位置。**resolveRequiredPlaceholders()**
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
/*占位符解析器解析并替换占位符*/
return this.propertyResolver.resolveRequiredPlaceholders(text);
}
这里其实是将解析的逻辑交给了属性解析器。**resolveRequiredPlaceholders()**
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
if (this.strictHelper == null) {
/*如果占位符解析器为空,就创建一个占位符解析器*/
this.strictHelper = createPlaceholderHelper(false);
}
/*真正去解析占位符的操作*/
return doResolvePlaceholders(text, this.strictHelper);
}
在这个抽象的解析器里面又通过委派模式委派给了真正的解析占位符操作的方法。 **doResolvePlaceholders()**
这里为什么要这么设计?这其实是两个扩展点,开发人员可以自己继承这两个抽象类,重写对应的方法,来实现定制化的解析占位符的逻辑。
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
/*使用传入的属性占位符解析器去解析并替换占位符*/
return helper.replacePlaceholders(text, this::getPropertyAsRawString);
}
这里交给了真正的属性解析器**PropertyPlaceholderHelper**
去解析属性占位符。
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
Assert.notNull(value, "'value' must not be null");
/*解析字符串类型的值*/
return parseStringValue(value, placeholderResolver, null);
}
将所有格式的**${name}**
占位符替换为从提供的**PropertyPlaceHolderHelper**
,**PlaceHolderResolver**
返回的值。
再往下就是具体的解析字符串的逻辑,没有什么继续的必要。
这里面主要体现的就是利用**抽象类**
和 **委派模式**
提供了默认的属性解析器实现,当然我们也可以提供自己的解析器,只需要继承相应的抽象类,实现相应的抽象方法。
3.容器刷新
解析完配置文件路径以后,就是判断容器是否已经刷新过,如果尚未刷新,就会进行容器的刷新动作。 **AbstractApplicationContext.refresh()**
@Override
public void refresh() throws BeansException, IllegalStateException {
//加锁是因为ioc容器只能有一个,防止重复创建
synchronized (this.startupShutdownMonitor) {
//准备开始容器刷新
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 获取当前系统的时间,给容器设置同步锁标识
prepareRefresh();
// 解析xml配置文件或注解 bean定义资源的载入,获取一个全新的bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 给容器中注册一些组件,添加切面,类加载器,表达式解析器,注解解析器,事件处理器
prepareBeanFactory(beanFactory);
try {
//为容器的某些子类指定后置处理器,子类可以通过重写这个方法,
// 在bean工厂创建并预备完成以后做进一步的设置
/*可以在bd创建出实例之前,对bd信息做进一步的修改*/
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
/**
* 执行bean工厂的后置处理器,先执行bean定义注册后置处理器,在执行bean工厂的后置处理器。
* 执行顺序:先执行实现了优先级接口的,在执行带有order的,最后执行其他的。
*/
invokeBeanFactoryPostProcessors(beanFactory);
// 获取所有的后置处理器,先注册带优先级的,在注册带order的,
// 在注册剩下的。注册一个ApplicationListenerDetector,
// 在bean完成创建后检查是是否是ApplicationListener,如果是,添加到容器。
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 做一些国际化相关的操作
initMessageSource();
// 初始化事件派发器:获取beanFactory,
// 从beanFactory获取事件派发器,如果没有,创建一个放到容器中。
initApplicationEventMulticaster();
// 留给子容器,子容器可以再容器刷新的时候加入自己的逻辑。
onRefresh();
// 为事件派发器注册事件监听器,派发一些早期事件。
registerListeners();
// 初始化剩下的所有的非懒加载的单实例bean。
finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,
// 回调onRefresh(),并发布容器的生命周期事件。
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
这个方法很长,也可以说是ioc容器的核心,这里面涉及到的关于Spring的额外的知识也比较繁多,在此会对相关内容进行一一列举。
4.属性资源设置与校验
首先会去获取当前系统的时间,给容器设置同步锁标识。 **prepareRefresh()**
protected void prepareRefresh() {
// 获取当前系统的时间
this.startupDate = System.currentTimeMillis();
//关闭状态设置为false
this.closed.set(false);
//激活状态设置为true
this.active.set(true);
//日志打印
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
} else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 留给子类扩展:可以做一些资源初始化
initPropertySources();
// 检验必须有环境变量 ,结合上面的方法可以设置哪些属性是必填的
/*demo:MyClassPathXmlApplicationContext*/
getEnvironment().validateRequiredProperties();
// 获取容器早期的事件监听器
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
// 如果已经有了,就先清空 在push
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 允许这些早期事件在容器刷新之后发布出去
this.earlyApplicationEvents = new LinkedHashSet<>();
}
�
这里面可以关注一下几个扩展点:
- 可以再子类做一些资源初始化的方法
**initPropertySources()**
- 对上一步设置的属性变量进行校验
**validateRequiredProperties()**
随后会获取到容器早期的一些事件监听器,这些早期事件会在容器刷新成功之后发布出去。
5.解析配置文件
这一步主要的操作就是解析Spring的配置文件或者注解标识的配置类,加载bean的定义信息 **BeanDefinition**
,简称bd。最后创建一个**BeanFactory**
,简称bf。
**obtainFreshBeanFactory()**
�
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//刷新bean工厂
refreshBeanFactory();
/**返回bean工厂*/
return getBeanFactory();
}
这里面主要的逻辑就在于bean工厂的刷新。 **refreshBeanFactory()**
@Override
protected final void refreshBeanFactory() throws BeansException {
/*如果已经有了bean工厂,通常情况下并不会,什么情况下会有?通过applicationContext直接调用refresh方法*/
if (hasBeanFactory()) {
/*销毁里面的所有bean*/
destroyBeans();
/*关闭bean工厂*/
closeBeanFactory();
}
try {
//不管上面是否已经有bean工厂存在,最终都会走到这里,去创建一个bean工厂
DefaultListableBeanFactory beanFactory = createBeanFactory();
/*设置序列化id*/
beanFactory.setSerializationId(getId());
/*对工厂进行一些定制化设置*/
customizeBeanFactory(beanFactory);
/*加载bean的定义信息*/
loadBeanDefinitions(beanFactory);
/*将当前类的bean工厂引用指向创建的bean工厂*/
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
这里可以关注两点:
- 如何创建一个bean工厂
**createBeanFactory()**
- 加载bd的信息
**loadBeanDefinitions(beanFactory)**
5.1 创建bean工厂
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
为当前的容器上下文创建了一个内部bean工厂,每次刷新的时候会尝试调用当前方法。默认是创建了一个_**DefaultListableBeanFactory**_
,并且将此上下文父级的内部bean作为父 bean工厂。可以再子类中覆盖,例如自定义_**DefaultListableBeanFactory**_
的设置。
5.2 BeanFactory
上面提到了一个**DefaultListableBeanFactory**
,那么都有哪些bean工厂呢?为什么有这么多bean工厂呢?
来到**BeanFactory**
的顶层接口,**BeanFactory**
作为顶层接口,提供了一些列操作工厂内对象的方法,有一点需要注意的。
/**
*
* 对FactoryBean的转义定义,因为如果使用bean的名字检索 FactoryBean 得到的对象
* 是工厂生成的对象,如果想要得到工厂本身,需要转义。
*/
String FACTORY_BEAN_PREFIX = "&";
�这是决定你获取当前工厂还是当前工厂内对象的一个重要标识符号,切记。**&**
接下来再去看 **BeanFactory**
的继承关系,作为顶层接口,我们自然是从上往下看。
�这里面列举了几个重要的Bean工厂,同时也可以看到,**DefaultListableBeanFactory**
本身其实是bean工厂的重要实现类。
从图上的继承关系可以看出:**ListableBeanFactory**
、**HierarchicalBeanFactory**
和 **AutowireCapableBeanFactory**
。
为什么要定义这么多层次的接口呢?
主要是为了区分在Spring内部操作过程中对象的传递和转化过程,对对象的数据访问所做的一些限制。这三个接口共同定义了 Bean的集合,Bean之间关系,Bean行为。
在 **BeanFactory**
里只对 IOC 容器的基本行为作了定义,根本不关心你的 Bean 是如何定义怎样加载的。正如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心。要知道工厂是如何产生对象的,需要看具体的 IOC 容器实现,Spring 提供了许多 IOC 容器的 实 现 。
**ApplicationContext**
是Spring提供的一个高级的ioc容器,他除了能够提供ioc容器的基本功能以外,还未用户提供了一些附加的服务:
- 支持信息源,可以实现国际化。
**MessageSource**
- 访问资源
**ResourcePatternResolver**
- 支持应用事件
**ApplicationEventPublisher**
容器本身其实也是扩展点,支持我们通过类的继承来做一些定制化实现。
5.3加载BeanDefinition
**loadBeanDefinitions(beanFactory)**
在**AbstractApplicationContext**
其实也是一个空方法,交给子类去实现。找到具体的实现**AbstractXmlApplicationContext**
。
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 创建一个xml 的beanDefinition加载器 这个玩意里面持有一个beanFactory的引用
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
/*给beanDefinition 加载器设置上下文环境 资源加载器 实体解析器*/
/*这玩意我记得都是用的默认的*/
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
/*初始化beanDefinition加载器*/
initBeanDefinitionReader(beanDefinitionReader);
/*使用beanDefinition加载器加载beanDefinitions*/
loadBeanDefinitions(beanDefinitionReader);
}
这里面需要关注两个方法:
- 初始化
**beanDefinition**
加载器**initBeanDefinitionReader()**
- 使用
**beanDefinition**
加载器加载**beanDefinitions**
**loadBeanDefinitions()**
不过在分析这两个方法之前,先明确一下**BeanDefinition**
。
5.4BeanDefinition
什么是BeanDefinition
?
**BeanDefinition**
作为定义Spring Bean 文件中bean的接口,可以说是bean的抽象的数据结构,它包括属性参数,构造器参数,以及其他具体的参数。
继承关系
**BeanDefinition**
继承了**AttributeAccessor**
和**BeanMetaDataElement**
接口,拥有了对元数据访问的功能。
看一下具体的代码
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/*单例的作用域*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
/*多例作用域*/
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/*用户*/
int ROLE_APPLICATION = 0;
/*某些复杂的配置*/
int ROLE_SUPPORT = 1;
/*完全内部使用*/
int ROLE_INFRASTRUCTURE = 2;
/*设置父类的名字*/
void setParentName(@Nullable String parentName);
/*获取父类的名字*/
@Nullable
String getParentName();
/*设置class类型名*/
void setBeanClassName(@Nullable String beanClassName);
/*返回当前bean的名字(并不是准确的名字,有些childBeanDefinition是继承自父bean的名字)*/
/*所以不能依靠该名字确定class的类型*/
@Nullable
String getBeanClassName();
/*设置作用域*/
void setScope(@Nullable String scope);
/*获取作用域*/
@Nullable
String getScope();
/*设置懒加载*/
void setLazyInit(boolean lazyInit);
/*判断是否懒加载*/
boolean isLazyInit();
/*设置依赖的bean*/
void setDependsOn(@Nullable String... dependsOn);
/*依赖的bean*/
@Nullable
String[] getDependsOn();
/*设置优先注入其他bean*/
void setAutowireCandidate(boolean autowireCandidate);
/*是否优先注入其他bean*/
boolean isAutowireCandidate();
/*设置优先自动装配*/
void setPrimary(boolean primary);
/*这个bean是否优先自动装配*/
boolean isPrimary();
/*设置工厂bean的名字*/
void setFactoryBeanName(@Nullable String factoryBeanName);
/*返回工厂bean的名字*/
@Nullable
String getFactoryBeanName();
/*设置工厂方法名*/
void setFactoryMethodName(@Nullable String factoryMethodName);
/*返回工厂方法名*/
@Nullable
String getFactoryMethodName();
/*获取构造函数的值*/
ConstructorArgumentValues getConstructorArgumentValues();
/*判断是否有构造器参数*/
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
/*获取参数的值*/
MutablePropertyValues getPropertyValues();
/*判断是否有属性参数*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/*设置初始化方法*/
void setInitMethodName(@Nullable String initMethodName);
/*获取初始化方法的名字*/
@Nullable
String getInitMethodName();
/*设置销毁方法的名字*/
void setDestroyMethodName(@Nullable String destroyMethodName);
/*获取销毁方法的名字*/
@Nullable
String getDestroyMethodName();
/*设置角色*/
void setRole(int role);
/*获取角色*/
int getRole();
/*设置描述信息*/
void setDescription(@Nullable String description);
/*获取描述信息*/
@Nullable
String getDescription();
// Read-only attributes
ResolvableType getResolvableType();
/*是否是单例的*/
boolean isSingleton();
/*是否是多例的*/
boolean isPrototype();
/*是否是抽象bean*/
boolean isAbstract();
/*获取资源描述*/
@Nullable
String getResourceDescription();
/*有些beanDeFInition会使用beanDefinitionResource进行包装,将beanDefinition描述为一个资源*/
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
具体实现
**RootBeanDefinition**
、**GenericBeanDefinition**
、**ChildBeanDefinition**
**RootBeanDefinition**
是最常用的实现类,它对应一般性的元素标签,**GenericBeanDefinition**
是自2.5以后新加入的bean文件配置属性定义类,是一站式服务类。在配置文件中可以定义父和子,父用**RootBeanDefinition**
表示,而子用**ChildBeanDefiniton**
表示,而没有父的就使用**RootBeanDefinition**
表示。
**AnnotatedGenericBeanDefinition**
以**@Configuration**
注解标记的会解析为**AnnotatedGenericBeanDefinition**
。
**ConfigurationClassBeanDefinition**
以**@Bean**
注解标记的会解析为**ConfigurationClassBeanDefinition**
。
**ScannedGenericBeanDefinition**
以**@Component**
注解标记的会解析为**ScannedGenericBeanDefinition**
。
总结一下:如果把ioc容器看成是一个飞机场,那么里面的bean对象就是一个个的飞机,bd则是对应的造飞机用的图纸,我们首先要拿到图纸,根据图纸才能造飞机。
5.5 初始化BeanDefinition加载器
**initBeanDefinitionReader()**
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
reader.setValidating(this.validating);
}
初始化加载此上下文的bean定义信息的bean定义读取器,默认实现为空。可以在子类中覆盖,例如关闭xml验证或者使用不同的_**XmlBeanDefinitionParser**_
实现。
5.6 加载bean定义信息
**loadBeanDefinitions()�**
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
/*这里实际上是一个钩子方法,经典的模板模式,子类根据需要对方法进行重写,实际上加载xml的时候,这里锤子也没拿到*/
Resource[] configResources = getConfigResources();
/*如果资源不为空,走这里的逻辑,但是上面已经分析过,实际上锤子也没拿到,所以走下面的逻辑*/
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
/*获取配置文件位置*/
String[] configLocations = getConfigLocations();
/*此时读取到了我们在配置文件指定的配置文件 beans.xml*/
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
/*断言 判空*/
Assert.notNull(locations, "Location array must not be null");
/*记录beanDefinition的数量*/
int count = 0;
/*迭代加载beanDefinition*/
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
/*方法重载*/
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
/*获取资源加载器*/
ResourceLoader resourceLoader = getResourceLoader();
/*如果资源加载器为空,抛异常*/
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
/*如果资源加载器是资源模式解析器类型的*/
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
/*
将xml配置文件加载到resources中,resource其实就是spring底层封装了很多的细节,
抽象出来的资源顶层接口
让开发人员不必专注于底层配置文件的加载细节
*/
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
/*加载beanDefinition*/
int count = loadBeanDefinitions(resources);
/*这玩意不知道是啥,反正是空,没啥锤子用*/
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}/*走到这里说明资源加载器肯定不是资源模式解析器类型的*/
else {
// 只能通过绝对网址加载单个资源
Resource resource = resourceLoader.getResource(location);
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
/*断言*/
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
/*迭代遍历加载*/
for (Resource resource : resources) {
count += loadBeanDefinitions(resource);
}
return count;
}
最终将加载到的所有**beanDefinition**
信息注册到**BeanDefinitionRegistry**
。这个**BeanDefinitionRegistry**
被**AbstractBeanDefinitionReader**
持有。
5.7 Resource
这里面涉及到了一个对象,**Resource**
。
Spring把其资源做了一个抽象,底层使用统一的资源访问接口来访问Spring的所有资源。即:不管什么格式的文件,也不管文件在哪里,到Spring底层,都只有一个访问接口,**Resource**
。
类结构图
类和接口的分析
- 可以看到有四个比较重要的接口:
**InputStreamSource**
、**Resource**
、**WritableResource**
、**ContextResource**
。 **InputStreamSource**
```java public interface InputStreamSource {InputStream getInputStream() throws IOException; }
3. `**Resource**`接口
接口中定义了对于资源的判断、对资源的获取、对资源描述的获取。通过该接口可以对资源进行有效的操作。但是`**Resource**`接口注重于对资源的读取。
```java
/**
* 接口中定义了对于资源的判断、对资源的获取、对资源描述的获取。通过该接口可以对资源进行有效的操作。但是Resource接口注重于对资源的读取。
*/
public interface Resource extends InputStreamSource {
/*判断是否存在*/
boolean exists();
/*判断是否可读*/
default boolean isReadable() {
return exists();
}
/*判断是否可以重复读取,如果为true表示不可以重复读取,在读取完成之后,需要关闭流*/
default boolean isOpen() {
return false;
}
/*判断是否是文件*/
default boolean isFile() {
return false;
}
/*获取URL地址*/
URL getURL() throws IOException;
/*获取URL地址*/
URI getURI() throws IOException;
/*获取文件*/
File getFile() throws IOException;
/*默认通过输入流获取nio的只读字节流管道*/
default ReadableByteChannel readableChannel() throws IOException {
return Channels.newChannel(getInputStream());
}
/*资源长度*/
long contentLength() throws IOException;
/*上次更新时间*/
long lastModified() throws IOException;
/*根据资源的当前位置,获取相对位置的其他资源*/
Resource createRelative(String relativePath) throws IOException;
/*返回资源名称*/
@Nullable
String getFilename();
/*返回资源描述*/
String getDescription();
}
**WritableResource**
因为Resource接口主要是注重对资源的读取,当我们对资源进行写入的时候,需要获取对应的判断和输出流。WritableResource接口主要定义了对写入的支持。
public interface WritableResource extends Resource {
/*返回资源是否可以被写入*/
default boolean isWritable() {
return true;
}
/*获取资源的写入流*/
OutputStream getOutputStream() throws IOException;
/*默认提供的支持写的nio字节管道*/
default WritableByteChannel writableChannel() throws IOException {
return Channels.newChannel(getOutputStream());
}
}
**ContextResource**
有些资源是相对于当前容器的,用来获取容器中的资源。
public interface ContextResource extends Resource {
String getPathWithinContext();
}
- 存在一个
**AbstractResource**
的抽象类,所有的对于资源获取都继承自**AbstractResource**
抽象类。 - 其余的都是具体的实现类,用来加载指定的资源。
对资源的加载
Spring框架为了更方便的获取资源,尽量弱化程序员对各个**Resource**
接口的实现类的感知,定义了另一个**ResourceLoader**
接口。接口有一个特别重要的方法:**Resource getResource(String location);**
返回**Resource**
实例。因此程序猿在使用spring容器的时候,可以不去过于计较比较底层的**Resource**
实现,也不需要自己创建**Resource**
的实现类,而是直接使用**ResourceLoader**
获取到bean容器本身的**Resource**
,进而获取到相关的资源信息。
**ResourceLoader**
只能对**classpath**
路径下面的资源进行加载,并且只会加载指定的文件
/**
* Spring框架为了更方便的获取资源,尽量弱化程序员对各个Resource接口的实现类的感知,定义了另一个ResourceLoader接口。
* 接口有一个特别重要的方法:Resource getResource(String location),返回Resource实例。因此程序员在使用Spring容器时,
* 可以不去过于计较底层Resource的实现,也不需要自己创建Resource实现类,而是直接使用ReourceLoader,获取到bean容器本身的Resource,
* 进而取到相关的资源信息。
*/
public interface ResourceLoader {
/** Pseudo URL prefix for loading from the class path: "classpath:". */
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
/*用来根据location来获取指定的资源*/
Resource getResource(String location);
/*获取类加载器*/
@Nullable
ClassLoader getClassLoader();
}
**ResourcePatternResolver**
表示会加载所有路径下面的文件,包括jar包中的文件。同时**locationPattern**
可以设置为表达式来加载对应的文件。
/*表示会加载所有路径下面的文件,包括jar包中的文件。同时locationPattern可以设置为表达式来加载对应的文件。*/
public interface ResourcePatternResolver extends ResourceLoader {
/**
* 表示会加载所有路径下面的文件,包括jar包中
*/
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
/**
* 根据
*/
Resource[] getResources(String locationPattern) throws IOException;
}
区别:
**classpath**:
:表示从类路径中加载资源,**classpath**
:和**classpath**
:/是等价的,都是相对于类的根路径。资源文件库标准的在文件系统中,也可以在JAR或ZIP的类包中。
**classpath**:*
:假设多个JAR包或文件系统类路径都有一个相同的配置文件,**classpath**
:只会在第一个加载的类路径下查找,而**classpath**
*:会扫描所有这些JAR包及类路径下出现的同名文件。
**DefaultResourceLoader**
spring实现的默认的加载器,一般其他的加载器会继承该类,并重写**getResourceByPath**
方法。
@Override
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
//循环遍历使用解析器解析该location的资源,如果资源不为空,直接返回
for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
/*以/开头那么根据path去寻找*/
if (location.startsWith("/")) {
return getResourceByPath(location);
}
/*以classpath开头,那么抽象为ClassPathResource*/
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
/*其他情况采用urlResource来加载*/
URL url = new URL(location);
return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
}
catch (MalformedURLException ex) {
// No URL -> resolve as resource path.
return getResourceByPath(location);
}
}
}
**PathMatchingResourcePatternResolver**
Spring提供了一个**ResourcePatternResolver**
实现**PathMatchingResourcePatternResolver**
,它是基于模式匹配的,默认使用**AntPathMatcher**
进行路径匹配,它除了支持**ResourceLoader**
支持的前缀外,还额外支持“**classpath**
:”用于加载所有匹配的类路径**Resource**
,**ResourceLoader**
不支持前缀“**classpath**
:”。
6.prepareBeanFactory(beanFactory)
给容器中注册一些组件,添加切面,类加载器,表达式解析器,注解解析器,事件处理器。 **prepareBeanFactory()**
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
/*类加载器*/
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
/*表达式解析器*/
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
/*属性编辑器*/
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 给当前工厂设置上下文回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
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.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory接口未在普通工厂中注册为可解析类型。
// 注册消息资源的解析器
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 将用于检测内部beans的早期后置处理器注册为ApplicationListeners。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
7.postProcessBeanFactory(beanFactory)
为容器的某些子类指定后置处理器,子类可以通过重写这个方法,在bean工厂创建并预备完成以后做进一步的设置,可以在bd创建出实例对象之前,对bd信息做进一步修改。**postProcessBeanFactory()**
这也是spring提供的一个扩展点。
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
8.执行bean工厂的后置处理器
执行bean工厂的后置处理器,先执行bean定义注册后置处理器,在执行bean工厂的后置处理器。执行顺序:先执行实现了优先级接口的,在执行带有order的,最后执行其他的。
**invokeBeanFactoryPostProcessors(beanFactory)**
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//执行bean工厂的后置处理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
**�invokeBeanFactoryPostProcessors()**
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
//初始化一个set列表,存储已经执行过的beanName
Set<String> processedBeans = new HashSet<>();
//类型断言:如果是BeanDefinitionRegistry类型的
//意思就是:当前 beanFactory 是 beanDefinition 的注册中心 , bd 全部注册到 bf。
if (beanFactory instanceof BeanDefinitionRegistry) {
//类型转换 bf -> bd注册中心
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//存储BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
/*存储BeanDefinitionRegistryPostProcessor*/
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
/**
* BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 之间的关系 ?
* BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子类。
* 它里面 搞了一个新的方法 postProcessBeanDefinitionRegistry ,可以往容器中注册更多的bd信息。
* 扩展点:
* ①BeanFactoryPostProcessor 对bd信息进行修改
* ②postProcessBeanDefinitionRegistry 添加更多的bd信息
*/
//处理ApplicationContext里面硬编码注册的beanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
/*如果当前后置处理器的类型是BeanDefinitionRegistryPostProcessor*/
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
/*将后置处理器转换为BeanDefinitionRegistryPostProcessor类型*/
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
/*执行后置处理器的方法 这里又是一个后置处理器的调用点*/
registryProcessor.postProcessBeanDefinitionRegistry(registry);
/*将执行完的后置处理器加入到集合中*/
registryProcessors.add(registryProcessor);
} else {/*此时说明后置处理器是一个BeanFactoryPostProcessor,直接加入到BeanFactoryPostProcessor的集合中。后续统一执行。*/
regularPostProcessors.add(postProcessor);
}
}
// 这里不要初始化FactoryBeans:我们需要保留所有常规bean的未初始化状态,
// 让bean工厂的后处理器应用于它们!在实现优先级的bean definition registry后处理器、
// Ordered、Ordered等之间进行分离。
/*当前阶段的registry后置处理器集合*/
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先执行实现了主排序接口的后置处理器 PriorityOrdered
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
/*判断对应的bean是否实现了主排序接口,如果实现了,就让该后置处理器添加到集合。*/
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
/*已经执行的后置处理器名字集合,因为接下来马上要执行这些后置处理器了。*/
processedBeans.add(ppName);
}
}
/*对后置处理器进行排序 根据 getOrder() 返回的值进行升序排序*/
sortPostProcessors(currentRegistryProcessors, beanFactory);
/*注册所有的后置处理器*/
registryProcessors.addAll(currentRegistryProcessors);
/*调用当前后置处理器的相关接口方法 执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry()*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
/*清空当前阶段临时的集合*/
currentRegistryProcessors.clear();
// 接着执行实现了Ordered接口的后置处理器 这里的后置处理器是普通排序后置处理器
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
/*确保每一个后置处理器只执行一次*/
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// 最后将剩下的后置处理器逐个执行
/*这个变量控制是否需要循环*/
boolean reiterate = true;
while (reiterate) {
reiterate = false;
/*从bean工厂拿BeanDefinitionRegistryPostProcessor的后置处理器*/
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
/*循环判断执行没执行过得*/
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
/*这里为什么吧变量设置为true?因为新注册的后置处理器,可能也是往容器中注册的 registry 类型的后置处理器*/
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
/*这里是执行BeanDefinitionRegistryPostProcessor 的父类 BeanFactoryPostProcessor 的方法*/
// 上面重复三遍是为了执行 BeanDefinitionRegistryPostProcessor 的方法,
// 但是,BeanDefinitionRegistryPostProcessor 还继承了 BeanFactoryPostProcessor
// 这里是为了执行所有后置处理器的
// (BeanFactoryPostProcessor)的 postProcessBeanFactory方法。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
/*这个方法就是执行BeanFactoryPostProcessor的方法*/
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
/*处理不是 BeanDefinitionRegistry 类型的后置处理器*/
else {
// 调用上下文实例注册的后置处理器
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
/**
* 上面处理的是硬编码的BeanDefinitionRegistry和BeanFactoryPostProcessor的后置处理器。
* 下面处理器的是普通的后置处理器。
*/
// 不要在这里初始化FactoryBeans:我们需要保留所有常规beans未初始化以让bean工厂后处理器应用于它们!
/*获取容器内注册的所有BeanFactoryPostProcessor集合。还是处理主排序,普通排序,为排序的后置处理器集合*/
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 在实现优先级有序、有序和其他的BeanFactoryPostProcessors之间进行分离。
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
/*包含说明已经执行过了,直接啥也不做跳过即可*/
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先,执行带有优先级接口的
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 接着执行实现了order接口的
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后执行其他剩余的
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 内存清理,帮助GC
beanFactory.clearMetadataCache();
/*思考:为什么spring要把这里代码逻辑写的这么麻烦?为了框架的健壮性,提供更好的扩展性,方便在不同阶段,针对不同的需求进行扩展。*/
}
9.注册后置处理器
获取所有的后置处理器,先注册实现主排序接口的,在注册实现Order接口的,最后注册剩下的。
注册一个**ApplicationListenerDetector**
,在bean完成创建后检查是否是**ApplicationListener**
,如果是,添加到容器。
/**
* 实例化并注册所有 BeanPostProcessor bean,如果给出,则遵守显式顺序。
* 必须在应用程序 bean 的任何实例化之前调用。
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//注册所有的后置处理器
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
**�registerBeanPostProcessors()**
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取到所有的BeanPostProcessor后置处理器的beanName数组
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 注册bean后置处理器检查器,当bean在bean后置处理器实例化期间创建时,
// 即当bean不适合被所有bean后置处理器处理时,它会记录一条信息。
/*后置处理器数量,计算方式beanFactory已经有的数量+1+后注册的。1?下面一行手动硬加的*/
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
/*BeanPostProcessorChecker? step into 检查创建bean实例的时候,后置处理器是否已经全部注册完毕,如果未完毕,日志提示。*/
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 分离 实现了主排序接口的后置处理器
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
/*存放mergedBeanDefinition后置处理器*/
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
/*普通排序接口的*/
List<String> orderedPostProcessorNames = new ArrayList<>();
/*没有实现排序接口的*/
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
/*循环将所有的后置处理器进行分离存放*/
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先注册实现了优先级接口的后置处理器
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 其次,注册实现了order接口的后置处理器
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 最终,注册所有剩下的所有后置处理器
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//注册后置处理器的逻辑 step into
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 最后,再次处理internalPostProcessors,确保存放mergedBeanDefinition后置处理器在链表的末尾
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
//重新注册后处理器时,将内部beans检测为ApplicationListeners,将其移动到处理器链的末端(用于获取代理等)。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
10.initMessageSource()
�
做一些国际化相关的操作。**initMessageSource()**
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
} else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
11.初始化事件派发器
**initApplicationEventMulticaster()**
�
初始化事件派发器,获取bean工厂,从bean工厂获取事件派发器,如果没有,创建一个放到容器中。
protected void initApplicationEventMulticaster() {
//获取bean工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//判断容器是否有事件派发器
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
//如果有就获取到引用 (用户自定义了一个事件多播器)
/*可以实现APPLICATION_EVENT_MULTICASTER接口来自己实现一个事件派发器,通过bean的方式传递给spring*/
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {//走到这里的前提是容器中没有事件派发器,需要使用spring框架默认提供的事件派发器。
//直接造一个事件派发器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//将事件派发器注册到一级缓存,事件派发器是单例的全局通用的。
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
12.onRefresh()
�
留给子容器,子容器可以在容器刷新的时候加入自己的逻辑。**onRefresh()**
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
13.注册监听器
为事件派发器注册事件监听器,派发一些早期事件。**registerListeners()**
protected void registerListeners() {
// 将所有的事件监听器(硬编码的)注册到事件派发器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 注册通过bean配置提供的监听器 ,用户可以通过 bd 的方式 提供listener
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 通过事件派发器派发容器早期应用程序事件 这里可以通过重写onRefresh方法直接往earlyApplicationEvents的set集合里面加。
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
�
关注一下:**ApplicationEventMulticaster.multicastEvent(earlyEvent)**
派发事件。
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
/*事件类型为空就是用默认的事件类型解析器*/
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
/*获取事件多波器的线程池*/
Executor executor = getTaskExecutor();
/*拿到当前事件的所有监听器,伦轮训所有的监听器,对事件进行派发。*/
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
**�invokeListener()**
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
/*获取到错误处理器的引用*/
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
/*真正执行派发事件的逻辑*/
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
**doInvokeListener()**
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
/*监听器发布事件*/
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
13.1 ApplicationListener
ApplicationListener && ApplicationEvent
通过自定义不同类型的事件,使用不同的监听器监听不同类型的事件,做到jvm进程内的消息队列,事件驱动,解耦。
public class MyEvent extends ApplicationEvent {
String message;
public MyEvent(Object source) {
super(source);
}
public MyEvent(Object source,String message) {
super(source);
this.message=message;
}
public void print(){
System.out.println("发布了一个事件:"+message);
}
}
public class MyListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
event.print();
}
}
/**
* 测试spring 的 ioc 容器的事件发布
*/
private static void testPublishEvent() {
ApplicationContext ioc = new ClassPathXmlApplicationContext(CONFIG_LOCATION);
ioc.publishEvent(new MyEvent("", "这是我自定义的一个事件"));
}
@EventListener
对上面写法的一个优化,更加简洁,开发量更少,懒人必备神器。
private static void testEventListener() {
ioc.publishEvent(new ApplicationEvent("hello,spring") {
@Override
public Object getSource() {
return super.getSource();
}
});
}
@Component
public class MyEventListener {
@EventListener(classes = ApplicationEvent.class)
public void listener(ApplicationEvent event){
System.out.println("event = " + event);
}
}
14.初始化剩下所有的单实例bean
**finishBeanFactoryInitialization(beanFactory)**
�
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 为此上下文初始化转换服务
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 如果容器里面没有字符串转换器,初始化一个字符串转换器放到容器中。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 尽早初始化LoadTimeWeaverAware beans,以便尽早注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停止使用临时类加载器进行类型匹配
beanFactory.setTempClassLoader(null);
// 允许缓存所有bean定义元数据,不期望进一步的更改,冻结bd信息,冻结之后就无法往bf注册bd了
beanFactory.freezeConfiguration();
// 实例化所有剩余的单实例bean
beanFactory.preInstantiateSingletons();
}
如何冻结bd信息的?**beanFactory.freezeConfiguration()**
@Override
public void freezeConfiguration() {
/*这个字段如果是true,name就不能往容器中添加新的beanDefinition了*/
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
**beanFactory.preInstantiateSingletons()**
这个方法内容过多且偏核心内容,留在下一篇分析,跳过这里,加载完所有的单实例bean之后,看还要做什么操作。
15.finishRefresh()
初始化容器的生命周期事件处理器,回调**onRefresh()**
,并发布容器的生命周期事件。**finishRefresh() **
�
protected void finishRefresh() {
// 清除上下文级资源缓存(例如来自扫描的ASM元数据)。
clearResourceCaches();
// 为此上下文初始化生命周期处理器。
/*案例演示:lifecycle package
* 两者的区别:
* smart:正常情况下就会执行
* 普通的:必须显示调用容器.start()/.stop()
* */
initLifecycleProcessor();
// 首先将刷新传播到生命周期处理器。回调 onRefresh
getLifecycleProcessor().onRefresh();
// 发布容器创建完成事件
publishEvent(new ContextRefreshedEvent(this));
// 注册容器上下文
if (!NativeDetector.inNativeImage()) {
LiveBeansView.registerApplicationContext(this);
}
}
15.1 为此上下文初始化生命周期事件处理器
**initLifecycleProcessor()**
�
protected void initLifecycleProcessor() {
/*获取bean工厂*/
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
/*判断工厂是否已经有生命周期处理器,有的话直接获取引用*/
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
} else {
/*此时就是工厂目前还没有的逻辑,那么就需要自动创建一个*/
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
/*注册到一级缓存*/
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
15.2 生命周期事件处理器
**Lifecycle**
&& **SmartLifecycle**
容器创建完成之后的回调,传递的参数_**autoStartUpOnly**_
是干嘛的?
表示只启动_**SmartLifeCycle**_
生命周期对象,并且启动的对象_**autoStartUpOnly**_
必须是true,不会启动普通的生命周期对象,false的时候,会启动全部的生命周期对象。
public class DemoLifeCycle implements Lifecycle {
private boolean running =false;
@Override
public void start() {
this.running=true;
System.out.println("demo one start!");
}
@Override
public void stop() {
this.running=false;
System.out.println("demo one stop!");
}
@Override
public boolean isRunning() {
return running;
}
}
public class DemoSmartLifeCycle implements SmartLifecycle {
private boolean running = false;
@Override
public void start() {
this.running=true;
System.out.println("demo two start!");
}
@Override
public void stop() {
this.running=false;
System.out.println("demo two stop!");
}
@Override
public boolean isRunning() {
return running;
}
}
15.3 回调onRefresh()
**onRefresh()**
@Override
public void onRefresh() {
/*传递的参数autoStartUpOnly是干嘛的?
* 表示只启动SmartLifeCycle生命周期对象,并且启动的对象autoStartUpOnly必须是true,
* 不会启动普通的生命周期对象,
* false的时候,会启动全部的生命周期对象。*/
startBeans(true);
this.running = true;
}
**startBeans(true)**
private void startBeans(boolean autoStartupOnly) {
/*获取到所有实现了生命周期接口的对象,包装到map内 k:beanName v: 生命周期对象*/
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
/*因为生命周期对象可能依赖其他生命周期对象的执行结果,所以需要执行顺序,依靠 smart生命周期接口实现的另一个接口 ,方法返回值越低,优先级越高 */
Map<Integer, LifecycleGroup> phases = new TreeMap<>();
/*遍历判断满足条件加入到集合
* 条件1:SmartLifecycle
* 条件2:自启动
* */
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
/*排序值*/
int phase = getPhase(bean);
phases.computeIfAbsent(
phase,
p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
).add(beanName, bean);
}
});
/*轮训启动所有的生命周期处理器*/
if (!phases.isEmpty()) {
phases.values().forEach(LifecycleGroup::start);
}
}
**start()**
public void start() {
/*members?看上面的add方法,相当于判断生命周期事件处理器是不是空,如果是空的话就没必要向下执行了。*/
if (this.members.isEmpty()) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Starting beans in phase " + this.phase);
}
/*对生命周期事件处理器进行一个排序*/
Collections.sort(this.members);
for (LifecycleGroupMember member : this.members) {
/*真正执行启动的逻辑*/
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
}
**doStart()**
/**
* 将指定的 bean 作为给定的 Lifecycle bean 集的一部分启动,确保首先启动它所依赖的任何 bean。
* @param lifecycleBeans a Map with bean name as key and Lifecycle instance as value
* @param beanName the name of the bean to start
*/
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
/*确保每一个生命周期处理器智只能被启动一次,在一个分组内被启动,其他分组内就看不到这个生命周期处理器*/
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
/*获取当前即将要被启动的生命周期处理器锁依赖的其他beanName*/
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
/*先启动当前生命周期处理器所依赖的其他lifeCycle*/
for (String dependency : dependenciesForBean) {
doStart(lifecycleBeans, dependency, autoStartupOnly);
}
/*
* 条件成立:执行start方法
* */
if (!bean.isRunning() &&
(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
if (logger.isTraceEnabled()) {
logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
}
try {
/*启动当前lifeCycle*/
bean.start();
}
catch (Throwable ex) {
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
}
if (logger.isDebugEnabled()) {
logger.debug("Successfully started bean '" + beanName + "'");
}
}
}
}
看完了启动,再看一下停止。
**stop()**
/**
* 停止所有注册的bean实现Lifecycle和当前正在运行。
* 任何实现SmartLifecycle bean 都将在其“阶段”内停止,
* 并且所有阶段都将从最高值到最低值排序。
* 所有未实现SmartLifecycle将在默认阶段 0 中停止。
* 声明为依赖另一个 bean 的 bean 将在依赖 bean 之前停止,无论声明的阶段如何。
*/
@Override
public void stop() {
/*停止所有的bean*/
stopBeans();
this.running = false;
}
**stopBeans()**
private void stopBeans() {
/*这里其实和启动的时候的逻辑是一样的。*/
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
int shutdownPhase = getPhase(bean);
LifecycleGroup group = phases.get(shutdownPhase);
if (group == null) {
group = new LifecycleGroup(shutdownPhase, this.timeoutPerShutdownPhase, lifecycleBeans, false);
phases.put(shutdownPhase, group);
}
group.add(beanName, bean);
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
/*注意这里是反向排序,启动的时候 1 2 3 4 5 关闭的时候就是 5 4 3 2 1*/
keys.sort(Collections.reverseOrder());
for (Integer key : keys) {
/*真正的核心逻辑在这里*/
phases.get(key).stop();
}
}
}
**stop()**
public void stop() {
/*如果为空,说明没有必要往下走了,直接返回。*/
if (this.members.isEmpty()) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Stopping beans in phase " + this.phase);
}
/*反向排序*/
this.members.sort(Collections.reverseOrder());
/*并发关闭smartLifeCycle*/
CountDownLatch latch = new CountDownLatch(this.smartMemberCount);
/*保存当前正处于关闭中的smartLifeCycle*/
Set<String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<>());
/*all 处理器*/
Set<String> lifecycleBeanNames = new HashSet<>(this.lifecycleBeans.keySet());
/*处理本分组内需要关闭的生命周期处理器*/
for (LifecycleGroupMember member : this.members) {
if (lifecycleBeanNames.contains(member.name)) {
/*真正执行关闭的逻辑*/
doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames);
}
else if (member.bean instanceof SmartLifecycle) {
// Already removed: must have been a dependent bean from another phase
latch.countDown();
}
}
try {
/*关闭主线程会在这里等待所有异步关闭的线程关闭完*/
latch.await(this.timeout, TimeUnit.MILLISECONDS);
if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isInfoEnabled()) {
logger.info("Failed to shut down " + countDownBeanNames.size() + " bean" +
(countDownBeanNames.size() > 1 ? "s" : "") + " with phase value " +
this.phase + " within timeout of " + this.timeout + "ms: " + countDownBeanNames);
}
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
**doStop()**
private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName,
final CountDownLatch latch, final Set<String> countDownBeanNames) {
/*吧要关闭的处理器从全局的集合移除掉并返回*/
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null) {
/*获取依赖当前bean的处理器*/
String[] dependentBeans = getBeanFactory().getDependentBeans(beanName);
/*递归关闭依赖的bean*/
for (String dependentBean : dependentBeans) {
doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames);
}
try {
if (bean.isRunning()) {
if (bean instanceof SmartLifecycle) {
if (logger.isTraceEnabled()) {
logger.trace("Asking bean '" + beanName + "' of type [" +
bean.getClass().getName() + "] to stop");
}
/*将当前的处理器名添加到countDownBeanNames内,这个集合表示正在关闭的smart bean*/
countDownBeanNames.add(beanName);
/*执行smart bean的关闭逻辑,看这个stop可以异步关闭,回调,999*/
((SmartLifecycle) bean).stop(() -> {
latch.countDown();
countDownBeanNames.remove(beanName);
if (logger.isDebugEnabled()) {
logger.debug("Bean '" + beanName + "' completed its stop procedure");
}
});
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Stopping bean '" + beanName + "' of type [" +
bean.getClass().getName() + "]");
}
/*普通生命周期处理器的关闭逻辑*/
bean.stop();
if (logger.isDebugEnabled()) {
logger.debug("Successfully stopped bean '" + beanName + "'");
}
}
}
/*如果是已经关闭的smart bean,直接跳过了,相当于...*/
else if (bean instanceof SmartLifecycle) {
// Don't wait for beans that aren't running...
latch.countDown();
}
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to stop bean '" + beanName + "'", ex);
}
}
}
}
15.4 发布容器创建完成事件
**publishEvent(new ContextRefreshedEvent(this))**
�
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
15.5 注册容器上下文
**LiveBeansView.**_**registerApplicationContext**_**(this)**
static void registerApplicationContext(ConfigurableApplicationContext applicationContext) {
String mbeanDomain = applicationContext.getEnvironment().getProperty(MBEAN_DOMAIN_PROPERTY_NAME);
if (mbeanDomain != null) {
synchronized (applicationContexts) {
if (applicationContexts.isEmpty()) {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
applicationName = applicationContext.getApplicationName();
server.registerMBean(new LiveBeansView(),
new ObjectName(mbeanDomain, MBEAN_APPLICATION_KEY, applicationName));
}
catch (Throwable ex) {
throw new ApplicationContextException("Failed to register LiveBeansView MBean", ex);
}
}
applicationContexts.add(applicationContext);
}
}
}
�至此,整个**refresh()**
的主流程已经完成。对于初始化所有的单实例bean,我将会在下一篇尽量做一个完整的分析。此外针对AOP,事务,三级缓存与循环依赖,加载spring mvc的组件,web环境下一个请求的执行流程,我都会在后续逐行分析源代码,做一些归纳总结。Spring发展至今,已经不单单是一个Java的框架,更是一个生态。