Spring加载IOC容器以及装载Bean源码解读
. SpringBoot应用开发已经非常普遍,确实,SpringBoot给我们的开发带来了很多便利,但其实,SpringBoot并没有增加什么新特性,只不过是在Spring注解的基础上做了升级版混合使用。SpringBoot的精髓就是自动装配(@EnableAutoConfiguration),我们不需要像以前使用Maven搭建项目时,引入过多的依赖包,同时还需要处理各种包冲突问题,简直是烦的要死,现在只需依赖SpringBoot核心包就能完成简单的应用开发了,所以了解Spring核心原理就非常重要了,下面我们开始从源码角度分析Spring底层原理。
. 下面我们首先定义一个实体类和配置类
/**
* @Description: Dog实体类
* @Auther: wenqi
* @Date: 2019/4/19 20:22
*/
@Data
@ToString
public class Dog {
private String name;
private Integer age;
public Dog(){
System.out.println("------>构造函数调用");
}
public void init(){
System.out.println("------>init函数调用");
}
}
/**
* @Description: Configuration配置类
* @Auther: wenqi
* @Date: 2019/4/19 20:30
*/
@ComponentScan("com.study.spring")
@Configuration
public class DogConfiguration {
public Dog dog(){
return new Dog();
}
}
接下来定一个测试类
/**
* @Description: 测试类
* @Auther: wenqi
* @Date: 2019/4/19 20:31
*/
public class Test {
@org.junit.Test
public void test(){
AnnotationConfigApplicationContext ac =new AnnotationConfigApplicationContext(DogConfiguration.class);
Dog dog = (Dog) ac.getBean("dog");
System.out.println(dog);
}
}
我们就从AnnotationConfigApplicationContext这个类开始,探究下Spring的IOC容器是如何装载Bean的,源码如下:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
//重点在下面这个方法,创建刷新容器
refresh();
}
然后,我们继续向下跟踪这个refresh()方法,这个方法在抽象类AbstractApplicationContext下
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1、刷新前的预处理
prepareRefresh();
// 2、获取BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3、BeanFactory的预准备工作(BeanFactory进行一些设置)
prepareBeanFactory(beanFactory);
try {
// 4、BeanFactory准备工作完成后进行的后置处理工作
postProcessBeanFactory(beanFactory);
// 5、执行BeanFactoryPostProcessor的方法
invokeBeanFactoryPostProcessors(beanFactory);
// 6、注册BeanPostProcessor(Bean的后置处理器),不同接口类型的BeanPostProcessor;在Bean创建前后的执行时机是不一样的
registerBeanPostProcessors(beanFactory);
// 7、初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
initMessageSource();
// 8、初始化事件派发器;
initApplicationEventMulticaster();
// 9、留给子容器(子类),空方法
onRefresh();
// 10、给容器中将所有项目里面的ApplicationListener注册进来
registerListeners();
// 11、重点在这,初始化所有剩下的单实例bean(自定义的单例bean)
finishBeanFactoryInitialization(beanFactory);
// 12、完成BeanFactory的初始化创建工作;IOC容器就创建完成
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();
}
}
}
通过以上步骤,我们发现Spring的IOC容器主要完成了以下操作:
1⃣️、Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息;
1)、xml注册bean;
2)、注解注册Bean;@Service、@Component、@Bean、xxx
2⃣️、Spring容器会合适的时机创建这些Bean
1)、用到这个bean的时候;利用getBean创建bean;创建好以后保存在容器中;
2)、统一创建剩下所有的bean的时候;finishBeanFactoryInitialization();
3⃣️、后置处理器;BeanPostProcessor
1)、每一个bean创建完成,都会使用各种后置处理器进行处理;来增强bean的功能;
AutowiredAnnotationBeanPostProcessor:处理自动注入
AnnotationAwareAspectJAutoProxyCreator:来做AOP功能;
xxx…
增强的功能注解:
AsyncAnnotationBeanPostProcessor
…
4⃣️、事件驱动模型;
ApplicationListener;事件监听;
ApplicationEventMulticaster;事件派发:
接下来,我们看下装载我们自己定义的单例bean的过程,主要通过11、finishBeanFactoryInitialization(beanFactory);方法来进行处理。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 1、判断有无ConversionService(bean属性类型转换服务接口),并初始化
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));
}
// 2、如果beanFactory中不包含EmbeddedValueResolver,则向其中添加一个EmbeddedValueResolver
// EmbeddedValueResolver-->解析bean中的占位符和表达式
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// 3、初始化LoadTimeWeaverAware类型的bean
// LoadTimeWeaverAware-->加载Spring Bean时织入第三方模块,如AspectJ
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 4、释放临时类加载器
beanFactory.setTempClassLoader(null);
// 5、冻结缓存的BeanDefinition元数据
beanFactory.freezeConfiguration();
// 6、重点来了,实例化所有剩余的(非lazy init)单例(包含自定义单例bean)
beanFactory.preInstantiateSingletons();
}
继续向下跟踪代码,6、beanFactory.preInstantiateSingletons()位于类DefaultListableBeanFactory下,源码如下:
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// 1、获取Bean的定义信息
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 2、触发初始化非懒加载单例beans
for (String beanName : beanNames) {
// 2.1、根据beanName获取bean的RootBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 2.2、判断为FactoryBean时
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 2.2.1、重点在这,获取创建bean
getBean(beanName);
}
}
// 非FactoryBean
else {
getBean(beanName);
}
}
}
// 3、所有Bean都利用getBean创建完成以后,检查所有的Bean是否是SmartInitializingSingleton接口的;如果是;就执行afterSingletonsInstantiated();
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
重点代码在 2.2.1、getBean(beanName);,根据beanName去获取单例bean信息,我们继续跟踪代码,位于类AbstractBeanFactory
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 1、转换bean的名称,去掉&前缀,且如果bean有别名的话,优先使用别名
final String beanName = transformedBeanName(name);
Object bean;
// 2、从缓存中获取bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 3、如果未能从缓存中获取到bean,则要重新创建bean
else {
// Fail if we're already creating this bean instance: We're assumably within a circular reference.
// 3.1判断指定的原型模式的bean是否当前正在创建(在当前线程内),如果是->则抛出异常(Spring不会解决原型模式bean的循环依赖)
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 3.2 检测bean definition是否存在beanFactory中
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果当前BeanFactory中不包含给定beanName的beanDefinition定义,且父beanFactory不为空,则去父beanFactory中再次查找
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 3.3 将name转换为原始beanName
// 因为这里的name已经经过beanName的规范处理,例如:&myBean-->规范-->myBean
// 所以当我们再次去父beanFactory查找时,要将beanName再次转换为原始的beanName,myBean-->回转-->&myBean
String nameToLookup = originalBeanName(name);
// 3.4 下面会递归调用各种getBean的方法重载,从当前bean的父factoryBean中加载bean
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 参数不为空,则委托parentBeanFactory使用显式参数调动
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// 参数为空,则委托parentBeanFactory使用标准的getBean方法获取bean
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
// 否则委托parentBeanFactory使用默认的getBean方法
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 3.3 如果当前bean不是用于类型检查,则将该bean标记为已经被创建或者即将被创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 3.4 合并beanDefinition,如果指定的bean是一个子bean的话,则遍历其所有的父bean
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 校验合并的beanDefinition,如果验证失败,则抛出异常
checkMergedBeanDefinition(mbd, beanName, args);
// 3.5 确保初始化当前bean所依赖的bean。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 循环所有的依赖bean,并递归实例化
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖
registerDependentBean(dep, beanName);
try {
// 实例化依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 3.6 创建单例bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 创建原型模式bean
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
该过程是为创建当前单例bean的准备工作。其中包括了:对BeanDefinition的检测、如果当前BeanFactory中不包含BeanDefinition则对父BeanFactory的检测、BeanDefinition的合并、依赖bean的初始化等。获取bean时,先从缓存Map中缓存中取,如果缓存中没有则到第3.6步,开始创建单例bean。
由于篇幅过长,在下面文章继续介绍Bean的创建过程~
上一篇: 启动MySQL报错_MySQL
推荐阅读
-
Spring源码剖析2:Spring IOC容器的加载过程
-
spring源码深度解析— IOC 之 开启 bean 的加载
-
Spring源码剖析2:Spring IOC容器的加载过程
-
# Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载
-
源码分析:Spring是如何把Bean注册到IOC容器中的?
-
Spring加载IOC容器以及装载Bean源码解读
-
Spring源码解读(2)IOC容器bean的实例化
-
Spring IOC 源码解析五(非延迟加载bean的初始化)
-
spring源码深度解析— IOC 之 开启 bean 的加载
-
荐 Spring源码之容器的基本实现:通过Xml配置装载Bean