1、IOC 依赖注入
IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spring 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。
2、Spring Bean
Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中的形式定义。
这里有三种重要的方法给Spring容器提供配置元数据。
- XML配置文件
- 基于注解的配置
- 基于java的配置
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();
}
}
}
3、bean生命周期
Bean的生命周期指的就是在上面三个步骤中后置处理器BeanPostprocessor穿插执行的过程
3.1 Bean创建的三个阶段
Spring在创建一个Bean时是分为三个步骤的
- 实例化,可以理解为new一个对象
- 属性注入,可以理解为调用setter方法完成属性注入
- 初始化,你可以按照Spring的规则配置一些初始化的方法(例如,@PostConstruct注解)
3.2 后置处理器
按照实现接口进行分类
- 直接实现了BeanPostProcessor接口
最简单的后置处理器,也就是说直接实现了BeanPostProcessor接口,这种后置处理器只能在初始化前后执行:
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;
}
}
- 直接实现了InstantiationAwareBeanPostProcessor接口
在第一种后置处理的基础上进行了一层扩展,可以在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;
}
}
- Spring内部专用的后置处理器
这种情况下再为属性注入阶段专门提供两个方法是不是有点多余呢?实际上第三种后置处理器是Spring为了自己使用而专门设计的:
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;
}
}
总结:
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个Bean的实例。
- 如果涉及到一些属性值 利用 set()方法设置一些属性值。
- 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。
- 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
- 如果Bean实现了 BeanFactoryAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
- 与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
- 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
- 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。