IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spring 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。
Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中的形式定义。
这里有三种重要的方法给Spring容器提供配置元数据。
2.1、ClassPathXmlApplicationContext 启动构建应用上下文:
外部使用
public static void main(String[] args) {
//根据 xml 文件内容来构建 ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationfile.xml");
}
启动过程
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
private Resource[] configResources;
// 如果已经有 ApplicationContext 并需要配置成父子关系,那么调用这个构造方法
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
...
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
setConfigLocations(configLocations);
if (refresh) {
refresh(); // 核心方法
}
}
...
}
refresh()初始化操作
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
this.prepareRefresh();
//提取配置信息,将配置文件解析成一个个 Bean 定义,注册到 BeanFactory 中,beanName-> beanDefinition 的 map
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
this.prepareBeanFactory(beanFactory);
try {
//Bean 如果实现了BeanFactoryPostProcessor此接口,那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。
this.postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
this.registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource
this.initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器
this.initApplicationEventMulticaster();
//钩子方法,初始化一些特殊的 Bean(在初始化 singleton beans 之前)
this.onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener接口
this.registerListeners();
// 初始化所有的 singleton beans
this.finishBeanFactoryInitialization(beanFactory);
//广播事件,ApplicationContext 初始化完成
this.finishRefresh();
} catch (BeansException var9) {
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
Bean的生命周期指的就是在上面三个步骤中后置处理器BeanPostprocessor穿插执行的过程
Spring在创建一个Bean时是分为三个步骤的
按照实现接口进行分类
public interface BeanPostProcessor {
// 初始化前执行的方法
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// 初始化后执行的方法
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
// 继承了BeanPostProcessor,额外提供了两个方法用于在实例化前后的阶段执行
// 因为实例化后紧接着就要进行属性注入,所以这个接口中还提供了一个属性注入的方法
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
// 实例化前执行
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
// 实例化后置
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
// 属性注入
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
// 推测bean的类型,例如在属性注入阶段我们就需要知道符合依赖类型的Bean有哪些
@Nullable
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
// 推断出所有符合要求的构造函数,在实例化对象的时候我们就需要明确到底使用哪个构造函数
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeansException {
return null;
}
// 获取一个提前暴露的对象,用于解决循环依赖
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
}