内容介绍
在Spring中应用上下文ApplicationContext是相较于BeanFacotry更为先进的IOC容器,BeanFacotry是Spring实现IOC最基础最核心的接口,使得Spring管理不同Java对象成为可能。而ApplicationContext是建立在ApplicationContext的基础上,提供了更多面向应用的功能。除了拥有BeanFactory的所有功能外,还支持特殊类型bean,如上一节中讲到的BeanFactoryPostProcessor和BeanPostProcessor两者的自动识别、资源加载、容器事件和监听器、国际化支持、单例bean自动初始化等。
BeanFactory是spring的底层基础设施,面向spring本身;而ApplicationContext面向spring的使用者,在开发中应该使用ApplicationContext。
我们一般称BeanFactory为Ioc容器,称ApplicationContext为应用上下文,通常ApplicationContext也被为Spring容器。
ApplicationContext添加了BeanFactoryPostProcessor和BeanPostProcessor的自动识别,不在需要我们像上一篇文章中一样手动添加了,只需要在xml中配置两者即可。
目前bean 的生命周期如下:
当前ApplicationContext的继承体系
代码分支
核心代码
ConfigurableApplicationContext
添加刷新容器的方法
public interface ConfigurableApplicationContext extends ApplicationContext {
/**
* 刷新容器
*
* @throws BeansException
*/
void refresh() throws BeansException;
}
AbstractRefreshableApplicationContext
/**
* ● @author: YiHui
* ● @date: Created in 23:40 2023/4/26
*/
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext{
private DefaultListableBeanFactory beanFactory;
/**
* 创建beanFactory并加载BeanDefinition
* @throws BeansException
*/
@Override protected void refreshBeanFactory() throws BeansException {
DefaultListableBeanFactory factory = createBeanFactory();
loadBeanDefinitions(factory);
this.beanFactory = factory;
}
/**
* 加载BeanDefinition
*
* @param beanFactory
* @throws BeansException
*/
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException;
/**
* 创建bean工厂
*
* @return
*/
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory();
}
public DefaultListableBeanFactory getBeanFactory() {
return beanFactory;
}
}
AbstractXmlApplicationContext
/**
* ● @author: YiHui
* ● @date: Created in 21:07 2023/6/12
*/
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext{
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException {
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);
String[] configLocations = getConfigLocations();
if(configLocations!=null){
xmlBeanDefinitionReader.loadBeanDefinitions(configLocations);
}
}
protected abstract String[] getConfigLocations();
}
AbstractApplicationContext
refresh()方法是AbstractApplicationContext类中一个重要的方法。它的主要作用是刷新应用程序上下文,即重新加载或更新上下文中的所有bean定义和配置。当调用refresh()方法时,Spring框架会执行以下关键步骤:
-
关闭旧的应用程序上下文(如果存在):首先,如果已经存在一个旧的应用程序上下文,refresh()方法会关闭它。这确保在刷新之前释放旧的资源,并清理任何可能的旧状态。
-
加载bean定义和配置:refresh()方法会重新加载上下文中的bean定义和配置。它会解析XML文件、注解或其他配置方式,并将这些定义转化为内部的数据结构,以便Spring能够了解和管理这些bean。
-
创建和初始化bean:refresh()方法会实例化和初始化所有定义的bean。它会根据bean定义的配置信息,使用适当的构造函数或工厂方法创建bean实例,并将其装配(注入)所需的依赖关系。
-
注册bean实例:已创建和初始化的bean实例将在应用程序上下文中注册,以便其他部分可以访问它们。这样,其他组件或类可以通过依赖注入或查找方式获取所需的bean。
-
完成刷新过程:在完成上述步骤后,refresh()方法会触发一些后续操作,如事件发布、AOP代理的创建等。这些步骤将上下文准备好,使其可以在应用程序中使用。
package org.springframework.context.support;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.DefaultResourceLoader;
import java.util.Map;
/**
* ● @author: YiHui
* ● @date: Created in 21:43 2023/4/26
* ● @notes: 抽象应用上下文
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
@Override public void refresh() throws BeansException {
//创建BeanFactory,并加载BeanDefinition
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//执行BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
//BeanPostProcessor的实例化提前与其他bean
registerBeanPostProcessors(beanFactory);
//提前实例化单例Bean
beanFactory.preInstantiateSingletons();
}
/**
* 注册BeanPostProcessor
* @param beanFactory
*/
private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for(BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
for(BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()){
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
}
/**
* 创建BeanFactory,并加载BeanDefinition
* @throws BeansException
*/
protected abstract void refreshBeanFactory() throws BeansException;
public abstract ConfigurableListableBeanFactory getBeanFactory();
@Override public Object getBean(String name) throws BeansException {
return getBeanFactory().getBean(name);
}
@Override public Object getBean(String name, Object[] args) {
return getBeanFactory().getBean(name, args);
}
@Override public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return getBeanFactory().getBeansOfType(type);
}
@Override public String[] getBeanDefinitionNames() {
return new String[0];
}
@Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(name, requiredType);
}
}
测试
spring.xml
配置BeanFactoryPostProcessor和BeanPostProcessor的实现。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="person" class="bean.Person">
<property name="name" value="yiHui"/>
<property name="car" ref="car"/>
</bean>
<bean id="car" class="bean.Car">
<property name="name" value="Rolls-Royce"/>
</bean>
<bean class="common.CustomBeanFactoryPostProcessor"/>
<bean class="common.CustomerBeanPostProcessor"/>
</beans>
ApplicationContextTest
@Test
public void testApplicationContext(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
Person person = applicationContext.getBean("person", Person.class);
//name属性在CustomBeanFactoryPostProcessor中被修改为YiHuiComeOn
System.out.println(person);
Car car = applicationContext.getBean("car", Car.class);
//brand属性在CustomerBeanPostProcessor中被修改为Maserati
System.out.println(car);
}
ClassPathXmlApplicationContext初始化的时序图
测试结果
processor执行成功
执行bean[customBeanFactoryPostProcessor]的初始化方法
执行bean[customerBeanPostProcessor]的初始化方法
CustomerBeanPostProcessor#postProcessBeforeInitialization
执行bean[car]的初始化方法
CustomerBeanPostProcessor#postProcessAfterInitialization
CustomerBeanPostProcessor#postProcessBeforeInitialization
执行bean[person]的初始化方法
CustomerBeanPostProcessor#postProcessAfterInitialization
Person{name='YiHuiComeOn', age='null', car=Car{name='Maserati'}}
Car{name='Maserati'}