一、前言
接触过java程序的小伙伴们,应该在相关应用日志里经常看到“xxxxFactory”的字眼,比如下面的报错,那这些factory是什么,又该怎样理解呢?这里咱们从非程序员来了解下Factory下的神秘面纱。
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.interceptor.CacheInterceptor#0'
: Cannot resolve reference to bean 'cacheManager' while setting bean property 'cacheManager';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cacheManager' available
二、spring Factory
Spring是java应用程序最常用的轻量级开发框架了,Spring的核心就是提供了一个IoC(Inversion of Control,控制反转,也就是反射,Java的反射是指程序在运行期可以拿到一个对象的所有信息;IoC通过依赖注入(DI)方式实现对象之间的松耦合关系,因此它也称依赖注入)容器,它可以管理所有轻量级的JavaBean组件,提供的底层服务包括组件的生命周期管理、配置和组装服务、AOP支持,以及建立在AOP基础上的声明式事务服务等。简单说,IOC容器就是由spring用来负责控制对象的生命周期和对象间关系的,是一个对象定义其依赖关系而不创建它们的过程。Spring提供了IOC容器的两种实现方式:
① BeanFactory:IOC容器的基本实现,是Spring内部的基础设施,是面向Spring本身的,不是提供给开发人员使用的。
② ApplicationContext:BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory。
Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,即FactoryBean。更多参看Java教程;在 Spring 中,构成应用程序主干(即应用程序由一个个bean构成的)并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。Factory bean跟普通bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂bean的getObject方法所返回的对象。工厂bean必须实现org.springframework.beans.factory.FactoryBean接口。综上,bean它是一个Java对象,是根据bean规范编写出来的类,并由bean容器生成的,这个对象就是一个bean。这样的话,java对象(实例化的bean)就可以被spring ioc容器(又称bean容器)来管理使用了。
1)Spring Bean初始化
所有spring bean 初始化都是由AbstractBeanFactory.doGetBean方法实现的。它先从三级缓存中获取,如果缓存中都没有。再去判断是否存在父容器,从父容器中获取。没有正式就进入bean 初始化流程,先根据beanName 获取到RootBeanDefinition,bean类元信息、先处理dependsOn中bean,保证bean依赖的创建顺序,下一步按照不同scope 进行bean 对象初始化。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//name 前缀处理 beanFactory beanName 带有&开头
String beanName = transformedBeanName(name);
Object beanInstance;
//从三级缓存去取bean,三级中都没有则返回null,说明对象还没有创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//如果缓存中bean 是FactoryBean实例,要通过接口获取到实际bean
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//判断bean对象标记是否正在创建中,如果正在创建中则不应该继续下去,出现依赖循环就会出现这个错误
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查父容器是否存在,尝试从父容器中获取
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
//缓存中标记beanName 正在被创建
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//bean 中@DependsOn 信息,用于标记bean之间初始化顺序,优先创建@DependsOn 中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 {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//创建单例对象
if (mbd.isSingleton()) {
//重点就在这里实例化对象 ,getSingleton 就是在这里将创建完成对象加入到一级缓存中
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex)
destroySingleton(beanName);
throw ex;
}
});
//如果生成bean 是FactoryBean ,再获取真正的对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//作用域 = prototype,因为不会放入缓存中,每次获取都要重新创建
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);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// session request 这些作用域,由作用域容器去管理这些对象
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
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);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
//返回初始化成功的对象,一个对象初始化就这样完成的了
return adaptBeanInstance(name, beanInstance, requiredType);
}
注意:bean创建都是伴随着三级缓存之间的转换完成的,对象不同状态分别存在不同缓存中;主要作用就是创建对象ObjectFactory首先放入三级换缓存(装载创建bean的工厂对象)中,当调用getObject 创建实例时,会将创建好对象加入二级缓存( 过早暴露单例对象,此时bean刚刚完成初始化,未完成属性注入和执行 init 方法)中,并且删除三级中缓存,当对象已经完成初始化方法和属性注入,再将缓存添加到一级缓存(用于存放完全可以使用单例bean,也就是初始化完成并且注入所有依赖)中,并且删除二级缓存。