最近读完《Spring技术内幕》一书,虽然此书评价貌似不高,但边看书边读源码,感觉还是有点收获,至少为阅读Spring源码提供了思路。然后这篇文章就记录一下这几天看Spring IOC这块的源码以及整体思路。
1、 BeanFactory与ApplicationContext
在Spring的IOC容器设计中,主要由两个容器系列:
- 实现BeanFactory接口的简单容器,提供了完整IoC容器服务支持,默认延迟初始化(lazy-load)——只有访问托管对象的时候,才会对对象进行初始化和依赖注入操作。
- 实现ApplicationContext接口的集成容器,在BeanFactory的基础上增加了更多复杂的企业级功能,容器启动时,就默认把所有的单例对象实例化完成。
2、 最简单的容器StaticListableBeanFactory
整个Spring容器中最简单的实现就是StaticListableBeanFactory,从它开始分析最合适不过了。
public class StaticListableBeanFactory implements ListableBeanFactory {
/** <BeanName, BeanInstance>的映射 */
private final Map<String, Object> beans;
// 默认构造会创建一个空的Map,自行调用addBean方法添加到容器中
public StaticListableBeanFactory() {
this.beans = new LinkedHashMap<String, Object>();
}
// 由外部预初始化一个Map
public StaticListableBeanFactory(Map<String, Object> beans) {
Assert.notNull(beans, "Beans Map must not be null");
this.beans = beans;
}
// addBean就是简单的将name和instance加入到Map中
public void addBean(String name, Object bean) {
this.beans.put(name, bean);
}
// 根据beanName从容器中获取Bean对象
@Override
public Object getBean(String name) throws BeansException {
// 处理"&"开头的BeanName(dereference解引用)
String beanName = BeanFactoryUtils.transformedBeanName(name);
Object bean = this.beans.get(beanName);
if (bean == null) {
// Bean不存在
throw new NoSuchBeanDefinitionException(beanName,
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
if (BeanFactoryUtils.isFactoryDereference(name) && !(bean instanceof FactoryBean)) {
// BeanName以"&"开头,但Bean不是FactoryBean
throw new BeanIsNotAFactoryException(beanName, bean.getClass());
}
if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
// Bean是FactoryBean,但BeanName不是"&"开头,则由FactoryBean创建Bean对象
try {
return ((FactoryBean<?>) bean).getObject();
}
catch (Exception ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
}
else {
// 其他情况直接返回Bean
return bean;
}
}
// 其余getBean方法(byName,byType)最终都是调用上面的getBean方法
...
// 判断bean是否为共享单例,也就是说调用getBean方法会始终返回同一个对象
// 注意:返回false,不一定说明是prototype的Bean,应该调isPrototype去显示检查是否是原型对象
@Override
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
Object bean = getBean(name);
return (bean instanceof FactoryBean && ((FactoryBean<?>) bean).isSingleton());
}
// 判断bean是否为原型实例,也就是说调用getBean方法会始终返回一个独立的新实例
// 注意:返回false,不应定说明是singleton的Bean,应该调isSingleton去显示检查是否是单例对象
@Override
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
Object bean = getBean(name);
return ((bean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) bean).isPrototype()) ||
(bean instanceof FactoryBean && !((FactoryBean<?>) bean).isSingleton()));
}
// 获取Bean的类型
@Override
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
String beanName = BeanFactoryUtils.transformedBeanName(name);
Object bean = this.beans.get(beanName);
if (bean == null) {
throw new NoSuchBeanDefinitionException(beanName,
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
// 如果是FactoryBean, 去看Factory创建的是什么类型的Bean.
return ((FactoryBean<?>) bean).getObjectType();
}
return bean.getClass();
}
...
}
3、 特殊的Bean对象——FactoryBean
Spring容器中有两种Bean:普通Bean和工厂Bean。Spring直接使用前者,后者以工厂模式生产Bean对象,并由Spring管理。
Spring设计FactoryBean的目的是为了将复杂对象的相关构造逻辑封装在类中,比如常见的ProxyFactoryBean。
另外一个目的是为了让我们能将依赖注入到一些第三方库的对象中,比如LocalContainerEntityManagerFactoryBean
负责JPA的EntityManagerFactory
的创建,ThreadPoolExecutorFactoryBean
负责线程池的创建,ForkJoinPoolFactoryBean
负责ForkJoinPool线程池的创建,ScheduledExecutorFactoryBean
负责调度线程池的创建…
但是Spring3.0基于Java注解的配置开始流行之后,这些FactoryBean基本都用不到了,这些对象我们可以通过@Bean方法的形式配置。
我个人大胆的猜测,FactoryBean是为了早期以XML配置对象的方式而设计的。
通过在BeanName前加上&
前缀我们能拿到FactoryBean工厂本身。比如:
public class MyBeanFactoryBean implements FactoryBean<MyBean> {
public MyBean getObject() throws Exception {
return new MyBean();
}
public Class<?> getObjectType() {
return MyBean.class;
}
}
// 直接通过beanName获取的是工厂创建的MyBean对象
beanFactory.getBean("myBean");
// 加&前缀获取的是MyBeanFactoryBean这个工厂本身
beanFactory.getBean("&myBean");
经常被问的一个问题是BeanFactory与FactoryBean的区别,用一句话总结起来:
BeanFactory代表Spring容器,而FactoryBean表示工厂类,其创建的对象被获取后作为容器中的Bean注册。
4、 核心容器DefaultListableBeanFactory
Spring IOC体系结构中最核心的容器实现类就是DefaultListableBeanFactory,它实现了ConfigurableListableBeanFactory和BeanDefinitionRegistry两个接口的功能。
4.1 、BeanDefinition、BeanDefinitionRegistry、BeanDefinitionReader
BeanDefinition用于描述一个Bean实例的scope、是否为懒加载、生命周期方法(init、destroy)、属性值、构造参数值以及组件依赖等信息。
BeanDefinitionRegistry就是BeanDefinition的注册表,提供了registerBeanDefinition(beanName, beanDefinition)
和removeBeanDefinition(beanName)
等相关方法。
BeanDefinitionReader负责从Properties、Xml、Groovy等配置文件中读取BeanDefinition,并将其注册到BeanDefinitionRegistry中。
4.2、基于Java注解的配置
Spring3.0之前只支持@Component、@Controller、@Service、@Repository这几个组件级的注解。
Spring3.0开始支持Java注解配置Bean对象,也就是通过@Configuration配置类中方法上的@Bean注解来定义Bean对象。
其中Bean被加入到Spring容器有两种方式:
1、register()方法直接以组件类的方式注册AnnotatedGenericBeanDefinition到容器中,具体实现在AnnotatedBeanDefinitionReader
中;
2、scan()方法通过扫描包下的所有组件类以批量的方式注册若干个ScannedGenericBeanDefinition到容器中,具体实现在ClassPathBeanDefinitionScanner
中;
如果注册的是@Configuration注解的类,则在ConfigurationClassPostProcessor处理器中将所有@Bean注解方法的Bean注册到容器中,这部分内容后面会讲BeanFactoryPostProcessor的时候再详细解析。
5、可配置的ConfigurableListableBeanFactory
ConfigurableListableBeanFactory结合了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory三个接口的功能。这三个接口也分别代表了Spring容器提供的三大基本功能:
ListableBeanFactory:根据类型或注解查找Bean
AutowireCapableBeanFactory:解析Bean的依赖关系并进行自动装配
ConfigurableBeanFactory:为容器提供了配置接口,以拓展容器的功能
我们想要拓展Spring IOC容器的功能主要就是通过ConfigurableBeanFactory开出的几个接口实现的:
5.1、BeanExpressionResolver
ConfigurableBeanFactory有两个关于Spring EL表达式的方法:
void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);
BeanExpressionResolver getBeanExpressionResolver();
在Spring中BeanExpressionResolver的实现是StandardBeanExpressionResolver
public class StandardBeanExpressionResolver implements BeanExpressionResolver {
/// ...
/** 该方法用于解析Spring EL表达式 **/
public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException {
if (!StringUtils.hasLength(value)) {
return value;
}
try {
Expression expr = this.expressionCache.get(value);
if (expr == null) {
expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
this.expressionCache.put(value, expr);
}
StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
if (sec == null) {
sec = new StandardEvaluationContext(evalContext);
///...做了一堆的配置
customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec);
}
return expr.getValue(sec);
}
catch (Throwable ex) {
throw new BeanExpressionException("Expression parsing failed", ex);
}
}
// StandardBeanExpressionResolver提供了一个方法允许我们进行重载
protected void customizeEvaluationContext(StandardEvaluationContext evalContext) {
}
}
StandardBeanExpressionResolver提供了一个customizeEvaluationContext
方法允许我们重载,我们唯一能做的就是对StandardEvaluationContext进行一些自定义配置。
5.2、Scope
Spring容器为我们提供了SCOPE_SINGLETON
和SCOPE_PROTOTYPE
两种基本的Scope,它还允许我们注册自己的Scope。比如Web应用中会用到的request
和session
两个Scope,另外Spring还提供了很多基础的Scope给我们,如线程级别SimpleThreadScope
、事务级别的SimpleTransactionScope
。
通常我们往容器中注册Scope只需调用beanFactory.registerScope
方法即可,另外Spring提供了一个BeanFactoryPostProcessor给我们——CustomScopeConfigurer。
关于BeanFactoryPostProcessor后面有一部分会介绍。
5.3、ConversionService
ConversionService,顾名思义,就是Spring提供给我们的类型转换服务。它主要有几种用途,解析配置文件中字符串,解析BeanDefinition中的property并绑定到对象中(DataBinder),解析Web应用中的请求参数并绑定到Controller的入参对象中(WebDataBinder),解析Spring EL表达式中的字面量。
除了ConversionService,ConfigurableBeanFactory还提供了PropertyEditorRegistrar、 TypeConverter、 StringValueResolver等接口用于处理Bean对象和类型转换。
关于Spring Converter的内容可以参考这几篇教程:
https://www.baeldung.com/spring-type-conversions
https://www.baeldung.com/spring-mvc-custom-data-binder
https://www.baeldung.com/spring-mvc-custom-property-editor
5.4、BeanPostProcessor
这个接口是用于扩展Spring功能的核心接口,事实上Spring容器本身的很多功能特性就是通过这个接口丰富的。
BeanPostProcessor有两个方法:
public interface BeanPostProcessor {
// 初始化方法之前调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// 初始化方法之后调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
很明显我们只要找到SpringBean什么时候初始化,就知道这两个方法什么时候被调用,Spring Bean的初始化分为四步:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/// ...
/// 这里是整个初始化过程的代码
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 第一步:调用Aware方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 第二步:调用BeanPostProcessor的postProcessBeforeInitialization方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 第三步:调用初始化方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 第四步:调用BeanPostProcessor的postProcessAfterInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
///...
}
- 第一步:调用Aware方法
private void invokeAwareMethods(final String beanName, final Object bean) {
/// 如果bean对象实现了相应的Aware接口,那这里会调用三种Aware方法:
/// BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
- 第二步:调用BeanPostProcessor.postProcessBeforeInitialization方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
/// 这个很简单:就是拿到BeanFactory里的所有BeanPostProcessor
/// 然后依次调用postProcessBeforeInitialization方法
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
- 第三步:调用bean对象的init方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
/// 先看有没有实现Spring定义的InitializingBean接口
/// 如果有的话就调用InitializingBean的afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
/// 然后调用自定义的init方法
/// 这个init方法是xml或@Bean注解配置的init-method属性
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
这里也许会有人想到使用JSR-250规范中定义的@PostConstruct注解进行初始化。
Spring提供了CommonAnnotationBeanPostProcessor和InitDestroyAnnotationBeanPostProcessor来处理JavaEE标准中的注解,如@PostConstruct、@PreDestroy、@Resource。
在InitDestroyAnnotationBeanPostProcessor中可以看到它是通过实现BeanPostProcessor#postProcessBeforeInitialization方法并在其中调用Bean的@PostConstruct注解方法的:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
/// 这里的initMethod就是通过@PostConstruct注解解析出来的方法
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
所以关于初始化方法的调用顺序是:
@PostConstruct==>InitializingBean.afterPropertiesSet==>Xml或@Bean中定义的init-method
而且Bean中@PostConstruct方法可以定义多个,但InitializingBean因为是接口所以afterPropertiesSet只有一个方法,init-method也只能有一个。
关于Spring初始化的过程可以参考这篇教程
-
第四步:调用BeanPostProcessor.postProcessAfterInitialization方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { /// 这个很简单:就是拿到BeanFactory里的所有BeanPostProcessor /// 然后依次调用postProcessBeforeInitialization方法 Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
用一张图总结一下:
5.5、BeanPostProceesor的常见实现
Spring内部实现各种Aware的ApplicationContextAwareProcessor;
Web应用中装配ServletContext的ServletContextAwareProcessor;
类加载时编织AspectJ切面的LoadTimeWeaver被LoadTimeWeaverAwareProcessor装配;
关于加载时编织参考Spring官方文档和AspectJ官方文档
另外还有几个基于AOP实现的BeanPostProceesor,最常用的就是@Async注解实现异步方法,而这个就是AsyncAnnotationBeanPostProcessor处理器实现的。
关于Spring异步方法的使用可以参考这篇教程
5.6、BeanPostProcessor的子接口
BeanPostProcessor有三个字接口:
1、InstantiationAwareBeanPostProcessor:添加了实例化对象的回调方法,以及属性值被自动装配时的回调;
2、DestructionAwareBeanPostProcessor:添加了销毁对象前的回调方法;
3、MergedBeanDefinitionPostProcessor:合并BeanDefinition后调用;
既然InstantiationAwareBeanPostProcessor是实例化和属性自动装配的回调,让我们看一下这块代码:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
///...
// Spring创建Bean对象的整个过程
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
/// 解析并加载BeanDefinition中定义的Class
/// ... 代码省略
/// ...省略异常处理代码
// 第一步:
// 调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// Processor的方法可能返回一个代理对象,
// 比如Spring AOP的自动代理(@EnableAspectJAutoProxy)。
// 这种情况比较少,可以不考虑
return bean;
}
/// ...省略异常处理代码
/// 根据BeanDefinition创建对象
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
/// 调用内部的创建方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 第二步: 实例化Bean对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 调用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
// 让Processor对BeanDefinition最后再进行一些处理
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
/// ...省略异常处理代码
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// 将Bean对象缓存起来以解决循环引用的问题
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
/// ...省略异常处理代码
// 填充Bean的属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化Bean对象
exposedObject = initializeBean(beanName, exposedObject, mbd);
///...
/// ...省略异常处理代码
// 注册Disposable接口和DestructionAwareBeanPostProcessor的DisposableBeanAdapter
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
///...
// 调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 自动装配对象
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称自动装配
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型自动装配
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
/// 调用InstantiationAwareBeanPostProcessor.postProcessPropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (pvs != null) {
// 将依赖的Bean对象注入到新创建的Bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
///...
}
至此,创建Bean的整个过程可以总结为下图:
6. 功能更强大的容器——ApplicationContext
ApplicationContext在BeanFactory容器的基础上继承了另外四个接口:
-
EnvironmentCapable接口:暴露了应用当前的环境配置信息的Environment接口。Environment提供了profiles和properties两方面的配置信息:
profiles指的是一组Bean的集合,这些Bean可以在xml中配置profile或着使用@Profile注解。Environment对于Profile来说,就是用于决定当前哪个profile被激活了,那个profile应该默认被激活。
Spring Profile的相关内容可以参考这篇教程
properties在应用中扮演着重要角色,主要来源形式有:properties文件、JVM系统参数、系统环境变量、JDNI、Servlet容器参数等。
-
MessageSource接口:提供了消息的参数化与国际化,避免了开发人员编写大量额外的代码处理各种复杂的情况。
在SpringBoot中使用MessageSource处理校验报错信息,可以参考这篇教程
-
ApplicationEventPublisher接口:为Spring容器提供了事件发布功能。ApplicationContext容器通过代理ApplicationEventMulticaster实现事件发布功能(具体可以参看AbstractApplicationContext的相关代码)。Spring容器本身也会发布各种事件,如ContextRefreshedEvent,ContextStartedEvent,RequestHandledEvent等。
-
ResourcePatternResolver接口:提供了解析资源路径的功能。如
/WEB-INF/*-context.xml
、classpath*:context.xml
这样的路径。
其次就是中间过渡的ConfigurableApplicationContext接口:
ConfigurableApplicationContext在ApplicationContext的基础上提供了一些配置接口,和ConfigurableBeanFactory类似,ConfigurableApplicationContext将配置和生命周期方法封装在此主要是为了避免对客户端代码可见,ConfigurableApplicationContext接口的方法应该只在应用启动和关闭的时候调用。这里面有这么几个方法比较重要:
// 启动容器加载配置并实例化所有的单例Bean
// 所有ApplicationContext容器必须refresh()了才能使用
void refresh();
// 关闭容器释放所有相关资源,包括销毁所有缓存的单例Bean
void close();
6.1、AbstractApplicationContext
先让我们看一下refresh()方法。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备ApplicationContext以进行refresh
prepareRefresh();
// 通知子类去刷新内部的BeanFactory
// AbstractApplicationContext提供了三个抽象方法由子类去实现:
// void refreshBeanFactory()
// void closeBeanFactory()
// ConfigurableListableBeanFactory getBeanFactory()
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 对这个BeanFactory进行配置
prepareBeanFactory(beanFactory);
try {
// 让子类再对BeanFactory进行相应的配置
postProcessBeanFactory(beanFactory);
// 调用BeanFactoryPostProcessor
// 并找到beanFactory容器中实现了BeanFactoryPostProcessor接口的bean,一起调用
// 主要这个这个接口和BeanPostProcessor有所区别
invokeBeanFactoryPostProcessors(beanFactory);
// 找出beanFactory中实现了BeanPostProcessor的Bean
// 并将它们以BeanPostProcessor的角色注册到beanFactory中
registerBeanPostProcessors(beanFactory);
// 初始化用于i18n的MessageSource
initMessageSource();
// 初始化用于事件分发的ApplicationEventMulticaster
initApplicationEventMulticaster();
// 让子类做一些其他的初始化,比如web应用中要初始化ThemeSource
onRefresh();
// 找到容器中所有的ApplicationListener并将其注册到ApplicationEventMulticaster中
registerListeners();
// 对BeanFactory进行最后的初始化,然后冻结配置,预初始化所有的单例对象
finishBeanFactoryInitialization(beanFactory);
// 最后一步:完成最后的刷新工作并发布ContextRefreshedEvent事件
finishRefresh();
}
///...
}
}
AbstractApplicationContext提供了很多模版方法给子类去实现,接下来我们看一下最主要的两个子类。
6.2、GenericApplicationContext与AbstractRefreshableApplicationContext
GenericApplicationContext和RefreshableApplicationContext两个体系内的容器实现本质上都是代理了DefaultListableBeanFactory提供的功能。
两者的区别在于GenericApplicationContext只能refresh()一次,而RefreshableApplicationContext允许refresh()多次。
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
/// ...
public GenericApplicationContext() {
// 在构造的时候就创建了beanFactory
// 之后的refresh()等操作都是对这个beanFactory进行操作
this.beanFactory = new DefaultListableBeanFactory();
}
///...
}
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
///...
@Nullable
private DefaultListableBeanFactory beanFactory;
public AbstractRefreshableApplicationContext() {
}
// 实现AbstractApplicationContext提供的模版方法
// 每次refresh()都会重新创建新的BeanFactory
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
// 销毁已有的容器
destroyBeans();
closeBeanFactory();
}
try {
// 创建新的容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
///...
}
6.3、BeanFactoryPostProcessor
不要将BeanFactoryPostProcessor和前面的BeanPostProcessor搞混,这个接口是BeanFactory初始化后的回调接口。
BeanFactoryPostProcessor可以与BeanDefinition进行交互并进行修改,但不能与Bean实例交互。这样做可能会导致bean过早实例化,从而违反了容器规则并造成了意外的副作用。如果需要与bean实例交互,请考虑实现BeanPostProcessor。
常见的BeanFactoryPostProcessor有CustomScopeConfigurer(自定义Scope)、CustomAutowireConfigurer(自定义@Qualifier)、CustomEditorConfigurer(自定义PropertyEditor)。它们都是用来扩展BeanFactory功能的。还有一个EventListenerMethodProcessor是用来处理@EventListener注解的。
BeanFactoryPostProcessor另一个核心的实现类就是ConfigurationClassPostProcessor,它是用来解析@Configuration注解类的处理器。
前面提到过Spring3.0开始支持@Configuration的配置,而它是由AnnotationConfigApplicationContext透出的,所以我们从这个类开发分析。
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
///...
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}
@Override
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}
///...
}
这里的AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner都是为了解析@Component注解并注册BeanDefinition。
当然这里的@Component还包括@Repository、@Service、@Controller、@Configuration这几个复合注解。
Annotate和Class在读取和扫描过程中都会去调用AnnotationConfigUtils
的registerAnnotationConfigProcessors
方法注册Spring的注解处理器,其中包括:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
// 注册@Configuration、@Bean、@Import、@ComponentScan等注解的ConfigurationClassPostProcessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册@Autowired、@Value等注解的AutowiredAnnotationBeanPostProcessor
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册处理@Required注解的RequiredAnnotationBeanPostProcessor
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 检查是否有JSR-250的依赖
// 有则注册处理@PostConstruct、@PreDestroy、@Resource等注解的
// CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 检查JPA的依赖, 有则注册处理@PersistenceUnit、@PersistenceContext注解的
// PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册处理@EventListener注解的EventListenerMethodProcessor
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
// 为@EventListener注解的方法提供一个事件类型适配器
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
这里我们主要关注ConfigurationClassPostProcessor,因为它实现了BeanDefinitionRegistryPostProcessor接口,所以它会回调两次:
1、先回调BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry方法,由ConfigurationClassParser解析出所有的ConfigurationClass,再由ConfigurationClassBeanDefinitionReader将所有的ConfigurationClass读取并将BeanDefinition注册到容器中。
2、然后回调BeanFactoryPostProcessor.postProcessBeanFactory方法,其中ConfigurationClassEnhancer使用Cglib对@Configuration类进行动态代理增强,主要是为了调用@Bean注解方法时由BeanFactory负责创建对象并将其放入容器中。
@Configuration
public class DemoConfiguration {
@Bean
public ObjectA a(){
return new ObjectA();
}
@Bean
public ObjectB b(){
// 正因为ConfigurationClassEnhancer
// 所以调用a()方法时会从BeanFactory中取出bean,而不是每次创建一个新对象
return new ObjectB(a());
}
}
对于ConfigurationClassPostProcessor更详细的源码分析请参考这两篇文章:
其中比较重要的是@Import注解的处理,因为Spring中很多@EnableXxx注解都是基于这个实现的。
@Import注解内可以填三种类型:
1、@Configuration注解类,2、ImportSelector接口实现类,3、ImportBeanDefinitionRegistrar接口实现类
@EnableXxx => @Import(XxxConfiguration ==> @Configuration) => XxxBeanPostProcessor
eg. @EnableScheduling
=> @Import(XxxSelector ==> ImportSelector)
eg. @EnableAsync、@EnableDubboConfig
=> @Import(XxxRegistrar ==> ImportBeanDefinitionRegistrar)
eg. @EnableAspectJAutoProxy、@EnableJpaAuditing、@EnableJpaRepositories
看一下这块的代码:
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
// 处理ImportSelector实现类
if (candidate.isAssignable(ImportSelector.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
// 如果实现的是DeferredImportSelector接口则延迟处理
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
// 直接拿到import的类,递归处理一下
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// 处理ImportBeanDefinitionRegistrar实现类
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
// 注解将ImportBeanDefinitionRegistrar放到configClass中
// 最后由ConfigurationClassBeanDefinitionReader处理
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// 否则当作@Configuration注解的类处理
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
至此已将Spring IOC的大部分核心内容的整体结构理清楚了,更多细节上的知识还需要查看源码去理解。
参考资料:
https://www.baeldung.com/spring-factorybean
https://www.baeldung.com/spring-profiles
https://spring.io/blog/2007/06/05/more-on-java-configuration
https://spring.io/blog/2014/11/04/a-quality-qualifier
https://spring.io/blog/2011/08/09/what-s-a-factorybean
https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2
https://spring.io/blog/2010/01/05/task-scheduling-simplifications-in-spring-3-0
https://spring.io/blog/2011/02/17/spring-3-1-m1-introducing-featurespecification-support
https://spring.io/blog/2016/03/04/core-container-refinements-in-spring-framework-4-3