引言
AbstractBeanFactory.getBean的流程,有点像老外点餐,不信咱们往下看。
入口
AbstractBeanFactory中有getBean的通用逻辑
//AbstractBeanFactory 中getBean方法第源码
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
核心逻辑在:doGetBean中。
逻辑说明:
getBean流程
老外点餐
获取BeanName,BeanFactory去掉&,根据别名找到对应的BeanName
饭店老板翻译老外说的
尝试从缓存中获取单例,如果存在就返回
餐馆老板看看有没有做好的,有就端出来给老外
检查是否是原型类型Bean在创建中,如果是,假设存在循环引用,抛出异常
老板看看是不是正在做,如果说是就不管了
找到定义bean对应的BeanFactory
老板找到张大厨
将多个GernericBeanDefinition合并为
RootBeanDefinition,如果Bean有父Bean,时会合并父类的相关属性
老板将客人的要求汇总给,供厨师使用
保证bean的依赖先初始化,对DependOn注解的支持
完成做这道菜的必须工作,例如洗菜
按不同作用域创建Bean
厨师做菜
如果需要进行类型装换
玩笑过后让我们看点实在的。
源码注释:
/**
* 获得一个实例,可以是共享(原型的),独立(单例的),指定的bean
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance
* using explicit arguments
* (only applied when creating a new instance as opposed to
retrieving an existing one)
* args (仅在创建一个新实例时使用,而不是获取一个已经存在的bean)
* @param typeCheckOnly whether the instance is obtained
for a type check,not for actual use
* 是否仅仅是类型检查
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly)
throws BeansException {
//1.获取对应的beanName ,BeanFactory去掉&,别名找到对应的BeanName
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//2. 尝试从缓存中获取单例 Spring会,在Bean未创建完成的情况下,创建Bean的ObjectFactory对象,提早曝光,以方便解决循环依赖。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//根据bean实例获取对象,如果是FactoryBean 获取它创建的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//3.原型依赖的检查,如果是原型,假设存在循环引用,抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 4.检查bean,是否定义在了BeanFactory中,
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果父BeanFactory不为空&&当前并没有beanDefinitionMap不包含,
// 委托给父BeanFactory
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
//委托给,需要参数的 getBean方法
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
// 委托给标准的getBean方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
//不仅是,类型检查,标记bean为创建
// 允许bean可以重新合并
markBeanAsCreated(beanName);
}
try {
//5.将GernericBeanDefinition转换为RootBeanDefinition,
//如果Bean有父Bean,时会合并父类的相关属性。
final RootBeanDefinition mbd =
getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that
// the current bean depends on.
// 6.保证bean的依赖先初始化了
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 对应@DependsOn 注解,
/**
* 检测是否存在 depends-on 循环依赖,若存在则抛异常。
* 比如 A 依赖 B,
* B 又依赖 A,他们的配置如下:
@Bean(name="a")
@DependsOn("b")public A a () {
return new A();}
@Bean(name = "b")
@DependsOn("a")
public B b () {
return new B();
}
* a 要求 b 在其之前被创建,但 b 又要求 a 先于它
* 创建。这个时候形成了循环,对于 depends-on 循环,Spring 会直接
* 抛出异常
*
*@see org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
*/
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//注册,Dependent和Bean的关系
registerDependentBean(dep, beanName);
try {
//先创建Dependent
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
//7.创建Bean的实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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);
}
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.
// 8.进行类型转换
// requiredType.isInstance(bean) 类似 bean instanceof requiredType
// 为true表示可以直接返回,或强转
//clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)
//仅当obj not null
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) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
一图胜千言(时序图)
当看完主流程时,我有如下疑问:
- getObjectForBeanInstance的作用?
- markBeanAsCreated 和getMergedLocalBeanDefinition的作用
- bean的DependsOn是什么?
- createBean的逻辑
getObjectForBeanInstance和createBean的逻辑下一篇再聊,预计20190921前上传。 这里先说下2,4。
补充说明:
markBeanAsCreated 和getMergedLocalBeanDefinition的作用
简单说,就是清除原有的RootBeanDefinition,再通过当前的多个GenericBeanDefinition合并成新的RootBeanDefinition,供BeanFactory使用。
什么是BeanDefinition
- BeanDefinition 是一个极简接口,主要目的是允许BeanFactoryPostProcessor(例如:PropertyPlaceholderConfigurer)去反射和修改属性值和其他的bean元数据。
- GenericBeanDefinition 用于一站式定义标准的bean。和其他beanDefinition一样,它允许指定一个类,属性值,可选的构造器参数值,并且可以通过配置parentName,来支持派生关系。
- RootBeanDefinition 代表合并的beanDefinition,Spring的BeanFactory使用RootBeanDefinition创建指定的bean它可能继承了多个原始的BeanDefinition,这些源BeanDefinition通常是GenericBeanDefinition,RootBeanDefinition本质上是运行时的“统一”bean定义视图。
如果有兴趣可以搜索
org.springframework.beans.factory.config.BeanDefinition org.springframework.beans.factory.support.GenericBeanDefinition org.springframework.beans.factory.support.RootBeanDefinition
bean的DependOn是什么?
我最开始以为是bean需要依赖,处理Autowired注解,然而不是。 利用IDEA查找了调用BeanDefinition的setDependsOn的地方,
发现了AnnotationConfigUtils.processCommonDefinitionAnnotations方法中如如下代码:
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
也就是说doGetBean中的
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
.....
}
是对@DependOn注解的支持,我孤陋寡闻,工作中重来没有使用过@DependOn注解。从网上查阅了资料。
当时我查下的资料的url:https://blog.csdn.net/qq_30257149/article/details/88350320
@DependOn注解用来表示一个bean A的实例化依赖另一个bean B的实例化, 但是A并不需要持有一个B的对象
啰嗦几句
读源码不容易,最开始我总是揪住一个方法不放,个把小时下来,已经不知道自己读到哪里了,后来总是囫囵吞枣,一味求快,好像看了很多,实际上什么也不知道。今年9月初,不知道是北京的天气变凉快了,还是什么别的原因,我自己也不清楚,竟然能静下心来,不求快,一层一层读,一点一点翻译,每天仅读40分钟,总算感觉是明白了点,不禁感慨如下:
只抓细节太糊涂
囫囵吞枣净瞎看
静心慢读未必快
反正我是入门了