spring版本:4.3.18
上一篇有说到过BeanDefinition,主要关注的是其扩展接口AnnotateBeanDefinition和其子类AnnotateGenericBeanDefinition。本篇先超前介绍spring是如果通过BeanDefinition来创建一个bean的。
BeanDefinition的注册
AnnotationConfigApplicationContext是GenericApplicationContext的子类,所以是使用内置DefaultListableBeanFactory工厂类完成bean的注册和创建的。
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
使用AnnotationConfigApplicationContext的任一构造方法【AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory)除外】实例化AnnotationConfigApplicationContext都会调用其无参构造方法,最终父类的GenericApplicationContext都会被调用,在父类的构造方法中创建了DefaultListableBeanFactory实例,这就是AnnotationConfigApplicationContext使用的bean工厂。
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
......
//如果当前bean工厂中存在beanName对应的BeanDefinition,那么oldBeanDefinition不为空。
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
......
//将新的替换旧的
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(256));
//alreadyCreated保存的是已经至少创建过一次的bean的名称
//hasBeanCreationStarted就是判断alreadyCreated是否是空的,没有存储任何beanName。
if (hasBeanCreationStarted()) {
//保证线程安全
synchronized (this.beanDefinitionMap) {
//beanDefinitionMap就是工厂用来保存描述bean的beanDefinition对象的。使用beanName作为beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
//将beanDefinitionNames指向新的beanName列表
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
//manualSingletonNames保存的是单例bean的名称
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 如果alreadyCreated为空,则说明仍在启动注册阶段
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
在下一篇介绍AnnotationConfigApplicationContext的启动流程会详细介绍何时调用这个registerBeanDefinition方法,被注解为bean的类何时被读取并创建BeanDefinition。
getBean的调用栈
调用AnnotationConfigApplicationContext的getBean方法最终会调用其内置bean工厂DefaultListableBeanFactory的getBean方法。
UserBean userBean = (UserBean) applicationContext.getBean("userBean");
userBean = applicationContext.getBean(UserBean.class);
AnnotationConfigApplicationContext并没有重写getBean方法,所以这里getBean调用的是其父类AbstractApplicationContext的getBean方法。
前面说了,AnnotationConfigApplicationContext是应用上下文,它管理bean的生命周期,但是它并不是真正的bean工厂。AbstractApplicationContext类中的getBeanFactory方法获取到的就是AnnotationConfigApplicationContext的内置 bean工厂DefaultListableBeanFactory。
@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
发现在AnnotationConfigApplicationContext的父类GenericApplicationContext重写了该方法。
【GenericApplicationContext类】
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
this.beanFactory就是DefaultListableBeanFactory。
private final DefaultListableBeanFactory beanFactory;
最终getBean调用的是DefaultListableBeanFactory的getBean方法。
DefaultListableBeanFactory类实现BeanFactory的其它父类未实现的getBean方法。
DefaultListableBeanFactory的父父类AbstractBeanFactory类实现了BeanFactory接口的三个getBean方法。
doGetBean方法
前面的所有getBean方法最终都是调用AbstractBeanFactory类的doGetBean方法的。doGetBean方法比较长,已经在源码中给出了注释。为了好看我将日记相关的代码去掉了。
【AbstractBeanFactory类】
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//根据传递进来的参数name获取beanName,
//一般情况下name就是beanName,如果是要获取BeanFactory对象的话,name是包含'&'字符的,所以需要先去掉'&'。
//最后调用canonicalName方法(确定原始名称,将别名解析为规范名称。)
final String beanName = transformedBeanName(name);
Object bean;
// 检查手动注册的单例缓存。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// isPrototypeCurrentlyInCreation返回指定的原型bean是否当前正在创建。如何当前正在创建则抛出BeanCurrentlyInCreationException异常。应该是避免多线程调用的。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 获取父bean工厂,检查父bean工厂中是否存在这个bean。
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//originalBeanName方法确定原始bean名称,将本地定义的别名解析为规范名称。如果name包含‘&’符号,则originalBeanName返回的name也包含&符号
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保初始化当前bean所依赖的bean已经创建。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//registerDependentBean为给定的bean注册依赖bean(在给定的bean被销毁之前被销毁)。
//这个方法和isDependent方法是配合使用确保依赖死循环的。
registerDependentBean(dep, beanName);
try {
//调用getBean方法让依赖的bean创建(如果没创建才会创建),最终还是调用doGetBean方法。
//如果依赖的bean又依赖其它bean那就先确保依赖的bean的依赖bean先创建,递归。
//所以前面的registerDependentBean方法和isDependent方法是解决无限递归调用的。
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 从这里开始创建bean实例
//如果BeanDefinition中描述这个bean是单例的
if (mbd.isSingleton()) {
//ObjectFactory,将bean的创建过程交给ObjectFactory完成。所以bean的创建是由对象工厂ObjectFactory创建的。
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//调用AbstractBeanFactory的createBean方法最终是调用其子类AbstractAutowireCapableBeanFactory的createBean方法创建bean。
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//异常则销毁这个bean
destroySingleton(beanName);
throw ex;
}
}
});
//获取给定bean实例的对象,对于FactoryBean,可能是bean实例本身,
//也可能是它创建的对象,由beanName是否包含'&'符合决定。
//如果该bean是一个FactoryBean且name没有'&'符号,那么就是调用该bean的getObject方法获取目标对象,
//如果该bean的is单例方法返回true那么目标对象将会被factoryBeanObjectCache所缓存。
//更多具体的就需要自己看源码了。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 不是单例,不用判断工厂中是否存在这个bean,直接创建一个新的实例。
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// 与前面如果是单例的时候ObjectFactory的getObject方法中调用的createBean方法是同一个方法,不重复描述了。
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//before、after这些就是调用些通知了,具体是啥自己去看源码。
afterPrototypeCreation(beanName);
}
//跟isSingleton的情况下注释相同
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 {
//其它如scope="request"的时候
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
//还是调用createBean方法创建对象
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
//跟isSingleton的情况下注释相同
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
......
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 如果getBean同时传入了requiredType和beanName
//则需要检查所需的类型是否与实际bean实例的类型匹配。
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
...
}
}
//将bean强转为我们需要的目标类型返回
return (T) bean;
}
createBean方法
从doGetBean方法的源码中可以看到,无论bean的scope是单例还是其它,最终都是调用createBean方法创建实际的bean,只不过如果是单例的会被bean工厂缓存下次调用doGetBean就从缓存中获取到了就不需要再次调用createBean方法创建bean了。单例缓存实例上就是保存在一个map对象中。
【DefaultSingletonBeanRegistry类】
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
至于单例是在什么时候被缓存的,可以回头看下doGetBean方法,在mbd.isSingleton的情况下,调用了getSingleton(beanName, new ObjectFactory