Spring生命周期Bean初始化过程详解
Spring生命周期Bean初始化过程详解
Spring 容器初始化
在spring中,不管是以xml文件的方式配置的Bean还是以注解的方式进行配置,最后都会将单例Bean放入到Spring的容器中,这里说的单例池不是说放入的Bean都是单例的,而是spring在单例池中的Bean都是单例的,只要你从单例池中取Bean对象,那么整个生命周期过程中都只有一个实例,但是你放入单例池的对象Bean它不是单例的,你可以不借助spring而自己产生多例,但是一般都没有这么做,只是时候在概念上要理解单例池和单例类的区别,spring容器的整个启动到初始化过程如下:
后面还会根据一些过程进行详细画图,这篇笔记主要介绍下Bean的初始化过程
Spring Bean初始化
在spring容器中有两种Bean,一种是普通的Bean,一种是FactoryBean,在介绍Bean的初始化之前,我们要先来理解这两种Bean的区别
BeanFactory和FactoryBean
BeanFactory和FactoryBea的的理解,相信在百度上一搜一大堆,就是说着两个有什么区别呢?
BeanFactory是spring的容器中的Bean工厂,Bean的创建,获取都是它来完成的,也就是说BeanFactory就是spring的容器,里面放入了所有的Bean,包括单例Bean,原型的Bean定义,也就是BeanDefinition,而FactoryBean也是一种Bean,FactoryBean是BeanFactory的一种Bean,是一种特殊的Bean,FactoryBean中是只能放入一种类型的Bean,而BeanFactory中可以放入不同类型的Bean,我们先来看下FactoryBean接口提供的方法,也就是它本身定义了提供了那些功能:
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
getObject():该方法就是你通过factoryBean放入容器的对象,也就是当你getBean的时候返回的就是spring调用getObject返回的Bean对象;
getObjectType():FactoryBean代表返回对象的类型
isSingleton:这是factoryBean默认的方法,你不需要实现,当然你也可以实现,默认是单例的bean
我们平时开发工程中使用的比较多的Mybatis就是用了FactoryBean,大家可能都知道,Mybatis中的Mapper是一个接口,而接口在spring容器中是不能实例化的,所以Mybatis就是利用了FactoryBean来重新构建了对象(通过反射)
我们简单来看下FactoryBean的例子:
@Component
public class BmlFactoryBean<T> implements FactoryBean<T> {
@SuppressWarnings(value = "unchecked")
@Override
public T getObject() throws Exception {
return (T) new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
AnnotationConfigApplicationContext c = new AnnotationConfigApplicationContext();
c.register(AppConfig.class);
c.refresh();
System.out.println(c.getBean("bmlFactoryBean"));
输出:com.bml.entity.User@6107227e
输出的是User对象,所以FactoryBean获取Bean返回的是geteObject返回的对象,在spring容器中存在两个Bean,一个是FactoryBean对应的对象,一个是FactoryBean中getObject返回的对象,所以是有两个Bean,而且如果通过
c.getBean(“bmlFactoryBean”)不管获取几次都是相同的对象,这里有一个重要的概念,我们都知道FactoryBean创建的对象都是单例Bean,但是一般的@Coponent创建的Bean和FactoryBean创建的对象有什么不同吗?
其实在上面的代码中,User对象的真正创建不是在18行代码,而是在20行代码,虽然我们的FactoryBean默认是单例的,但是FactoryBean只有在第一次getBean的时候才会放入到单例池,也就是说FactoryBean默认是懒加载的
而在spring容器中最终会出现两个Bean,比如就上面的代码,那么beanName=bmlFactoryBean是对应的我们的User Bean对象,而beanName=&bmlFactoryBean对应的是我们的FactoryBean本身的Bean对象
看上图,其中BeanFactory中的单例池是singletonObjects是存放了加了@Coponent注解的单例Bean,而上面的代码的FactoryBean是放在了单例池中的,而FactoryBean中getObject返回的对象的Bean是放在了factoryBeanOjectCache中的,看上图几非常清楚了;而我们通过ApplicationContext的getBean去获取FactoryBean的时候,如果beanName前面加了&就表示获取本身的FactoryBean,而不加&则表示获取FactoryBean中的getObject返回的对象。
源码分析
Bean的实例化
Bean的实例化可以说spring里面最核心的也是比较复杂的,也是比较绕的地方,bean的实例化是在DefaultListableBeanFactory中的preInstantiateSingletons方法开始的,这篇笔记主要把bean的初始化过程简单过一遍,有些地方太多了,后面笔记会慢慢写,这里主要把这个方法的前几个过程记录一下。
preInstantiateSingletons
/**
* 单例Bean的初始化
*
* @throws BeansException
*/
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
/**
* beanNames就是spring扫描得到的所有beanName都放在一个集合list中在
*/
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//然后根据beanNames循环开始初始化Bean
for (String beanName : beanNames) {
//这个过程就是合并bean的过程,合并bean的过程有点绕,反正流程就是将Bean合并成了一个RootBeanDefinition
//因为spring在扫描的过程中会把Bean扫描成GenericBeanDefinition,GenericBeanDefinition是
//可以设置父子bean的,而RootBeanDefinition设置父亲BeanName的时候会直接报错的,因为
//RootBeanDefinition是*BeanDefinition,是没有父亲Bean的
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//判断这个Bean不能是抽象的,不是延迟加载的,并且是单例的bean才会进行初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//实例化的第一步是先看下你是不是FactoryBean
if (isFactoryBean(beanName)) {
//如果是FactoryBean,这里就是FactoryBean的一个很重要的概念了,下面的代码
//Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);这里是在创建单例Bean,但是请注意,这里创建的Bean是FactoryBean,它只是spring容器中一个普通Bean
//这里创建的bean只是FactoryBean本身,比如我们的DemoFactoryBean,那么这里创建的就是DemoFactoryBean本身的对象,而不是它getObject()方法返回的对象bean
//所以针对FactoryBean来说,FactoryBean本身对象的beanName是以&beanName形式存在的,但是请注意,在缓存map中还是去掉了&的,都是以beanName的形式存在的
//如果是factoryBean,并且是单例的bean,那么factoryBean本身的对象存在signletonObjects,而factoryBean的getobject返回的对象在factoryBeanObjectCache中
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
//这个变量isEagerInit是什么意思呢?它的意思就是表示是不是马上加载的意思,用在这里我们猜一猜也就知道了
//你想哈,我们知道FactoryBean虽然设置为单例的,但是其实得到factoryBean的getobject对象是在你在getBean的时候并且beanName没有带&才会去创建
//简单来说,就是facatoryBean是懒加载的,下面的这个参数的意思就是说你是不是要马上加载,不是懒加载,而是马上加载到容器中
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
} else {
//注意看这个代码,这个代码的意思就是说你的FactoryBean是不是SmartFactoryBean,
//SmartFactoryBean也是一个Factorybean,但是它比FactoryBean多了一个功能就是可以设置为非懒加载的,也就是立马初始化
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
//初始化Bean
getBean(beanName);
}
}
} else {
//初始化Bean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
//bean初始化完成过后,单例bean初始化的回调方法,但是要实现了SmartInitializingSingleton才有
// /实现该接口后,当所有单例 bean 都初始化完成以后, 容器会回调该接口的方法 afterSingletonsInstantiated。
//主要应用场合就是在所有单例 bean 创建完成之后,可以在该回调中做一些事情
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
我这里画了一个简单的图,自己画的图可能不太准确,但是基本上也覆盖了bean初始化的一些过程,其中getBean没有详细的流程图,因为getBean这个太复杂了,后面会根据getBean再细化,这篇笔记主要讲bean初始化过程大概清楚一个整体流程
getMergedLocalBeanDefinition
合并bean的方法,很多解释我都写在代码注释里面了,这里就不多废话了
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
//先从合并的BeanDefinition的缓存中取RootBeanDefinition看有没有,没有才去创建
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
/**
* Return a RootBeanDefinition for the given bean, by merging with the
* parent if the given bean's definition is a child bean definition.
* @param beanName the name of the bean definition
* @param bd the original bean definition (Root/ChildBeanDefinition)
* @param containingBd the containing bean definition in case of inner bean,
* or {@code null} in case of a top-level bean
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws BeanDefinitionStoreException in case of an invalid bean definition
* 合并Bean的真正逻辑,涉及的概念,父子容器、父子Bean合并,非父子Bean,
* 将GenericBeanDefinition单独封装成一个RootBeanDefinition
*/
//参数containingBd就表示合并过后的bean,什么意思呢?就是如果你传入的containingBd不为空,则就不用合并了
//它本身就是一个合并过后的bean
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
//线程安全来处理逻辑
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
//如果containingBd为空,则重新去合并bean的缓存池重新拿RootBeanDefinition
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
// 这里判断你传入的bd是否存在父子关系,这里我们需要知道的是GenericBeanDefinition中是可以设置parentName的
//也就是说可以设置父亲BeanId,而RootBeanDefinition是不能设置的,设置直接报错,这个概念要理解清楚
//下面的逻辑就是说你传入的bd如果本身就是一个RootBeanDefinition,那么直接返回
//如果不是,那么就强制封装一个RootBeanDefinition返回给你
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
//代码逻辑到这里的时候就表示存在父子关系的bean,通过父亲的Beanname递归调用getMergedBeanDefinition
//因为你的父子Bean可能存在多层关系,父子的父子的父子是有可能存在的,所以这里是递归,如果说孩子的beanName和
//父亲的beanName一样,那么可能会出现在父子容器,就是说我的父亲可能在父容器里面,所以else就是去父容器
//中找寻这个bean,也是一样的逻辑,在父亲的容器中递归获取Bean
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
//到这里就是合并bean了,声明一个RootBeanDefinition,然后将子bean的属性都设置到mbd中
//这样就完成了一个合并,也不能说合并,就是创建了一个新的RootBeanDefinition,然后这个beanDefinition是
//包含了父子合成的属性存在于容器中的,而原来的父亲的bean在容器中也没有改变,因为这里是new的一个
//所以之前的那个父亲的beanDefinition也是没有改变的,还是在原来的容器中,这里是新创建的
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
// 合并过后的RootBeanDefinition,放入到mergedBeanDefinitions缓存中
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
getBean方法
//这个方法特别长,因为这个方法包含了创建bean,获取bean
/**
* Return an instance, which may be shared or independent, of the specified 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)
* @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
* 这里是创建Bean,在spring启动容器的过程中可能会调用多次,同一个Bean的创建可能会创建多次,因为可能会出现循环依赖
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//对beanName进行处理,看是否是带了&字符和这个name是不是以别名的形式传入的
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//getSingleton是从单例池中获取,是根据Beanname去获取,如果第一次肯定为空
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 + "'");
}
}
//如果单例池中获取到了对象,那么根据下面的代码去判断这个对象是不是factoryBean,如果是factorybean
//
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//和循环依赖有关,后面说
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//下面的if else逻辑就是去父容器中找看是否有,找到就直接返回
BeanFactory parentBeanFactory = getParentBeanFactory();
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.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//beanName在容器中还不存在,然后在父工厂也不存在,那么就会走到这里
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//下面就是看beanName是否有设置依赖,这个依赖是强依赖,是程序员自己设置的强依赖,强依赖简单理解就是我在初始化自己的时候,看下有没有强依赖的bean,如果有
//那么先去实例化依赖的bean,这样我们可以做一些自己的事情,比如我的实例化必须要依赖于某个bean,就可以这样使用
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
//这里是判断我依赖的ban有没有依赖我,简单来说就是我们两个Bean有没有相互依赖,也就是说循环依赖,如果存在循环依赖,直接报错
//这里的循环依赖不是bean组合额循环依赖,组合使用的循环依赖spring是可以解决的,但是@DependOn是没有办法解决的
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//登记当前beanName依赖的的beanName dep
registerDependentBean(dep, beanName);
try {
//实例化要依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
/**
* 上面一直没有获取到bean对象,并且处理了依赖的ban,下面就开始处理自己了
*下面的逻辑就是根据作用域去获取创建bean
* 1.单例bean
* 2.原型bean
* 3.web bean(scope=request or session),在spring mvc中使用
*/
// Create bean instance.
if (mbd.isSingleton()) {
//如果是单例的,下面的代码上面说过了,反正就是创建bean,createBean这个方法最核心,也太复杂,包括后续的执行流程都在里面
//这个createBean方法后面还有笔记要写很久
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()) {
//如果是原型的bean,那么这里进行创建
// 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 {
//代码走到这里,则证明你的这个bean不是单例的,也不是原型的,而是rquest或者session的bean
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
//scopes中存放了request bean和sessionbean的beanNames
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
//创建request bean或者sessionBean,下面的代码是lambad表达式,也就是get方法需要有一个参数Objectfactory,也就是具体的实例
//这里简单说下这里面的逻辑,里面的逻辑简单来说就是通过获取到的objectInstance
//然后使用request.getAttrbute(beanName)获取,如果获取到了就返回吗,没如果没有获取到,通过lambad表达式返回的bean对象,
//然后放入request或者session中,然后返回
//这里重要的是这个bean是在request中或者session中,取决于你的scope属性
//spring这里巧妙的使用了web的特性来存储web 创建的bean
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) {
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
getObjectForBeanInstance方法比较重要,spring这里每次获取bean后都要调用它,就是为了知道到底是一个普通bean还是factorybean的获取,如果是普通bean的获取,直接返回,如果是factorybean的获取,要去factoryBeanObjectCache中获取
/**
* Get the object for the given bean instance, either the bean
* instance itself or its created object in case of a FactoryBean.
* @param beanInstance the shared bean instance
* @param name the name that may include factory dereference prefix
* @param beanName the canonical bean name
* @param mbd the merged bean definition
* @return the object to expose for the bean
* 这里传入的参数name=原生传入的beanName没有做过处理的beanName,而beanName是经过处理过后的beanName
*/
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//这里判断的时候你的元素name是不是以&开头,如果是,则证明你要获取的是factoryBean本身的对象,而不是factoryBean的getObject
//要返回的对象
if (BeanFactoryUtils.isFactoryDereference(name)) {
/**
* 下面的判断分为几步:
* 1.你这个Bean是factoryBean了,判断从单例池中获取到的对象是不是NullBean,如果是,直接返回
* 2.如果不是NullBean,那么你必须是FactoryBean,否则直接报错
* 3.否则就直接返回
*/
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//这里再次判断了一下,如果上面的代码没有执行,也就是说你的beanname不是&开头的,beanInstance也不是FactoryBean
//类型,如果不是factoryBean,就直接返回bean对象本身
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
/**
* 到下面的逻辑就证明就是一个FactoryBean了,并且是要获取FactoryBean中getObject返回的对象
*/
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//从factoryBeanObjectCache中获取对象,factoryBeanObjectCache是放了FactoryBean中getObject返回的对象的缓存
object = getCachedObjectForFactoryBean(beanName);
}
//如果没有拿到对象,也就是在factoryBeanObjectCache中没有获取到,则证明是第一次,那么这里
//去调用FactoryBean中的getObject返回拿到bean对象
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//这里还涉及到一个重要的知识点,就是合并bean的概念,spring中扫描得到的BeanDefinition是GenericBeanDefinition,
//而合并过后就是一个RootBeanDefinition,所以如果传入的mbd为空,则证明还没有合并过这个Bean,那么我们要明白只要进入
//单例池创建的Bean,都是通过RootBeanDefinition来进行创建的,所以这里有一个重要的概念就是如果这个Bean还没有合并过
// 那么这里就需要合并一下,合并Bean一个重要概念就是父子Bean,当然以注解方式的配置的Bean,目前好像还没有配置父子Bean的地方
//但是在xml方式的时候就会有,如果合并bean的过程中,发现没有父子Bean,那么也会封装一个RootBeanDefinition
//如果有父子Bean,那么这里会将父子Bean合并,也就是将子Bean的属性填充到父Bean里面成为一个完整的Bean
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//这个方法里的代码就非常简单了,就是通过FactoryBean的getObject方法获取返回的对象,然后将这个对象放入到了
//FactoryBean的缓存factoryBeanObjectCache中
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
getObjectFromFactoryBean方法就是去factoryBeanObjectCache获取,如果factoryBeanObjectCache没有,则调用factoryBean的getobject方法,然后将调用返回的object 放置到factoryBeanObjectCache中,最后返回
例子分析
@DependsOn
在spring的容器中,程序员手动配置的强制依赖可以通过@DependsOn,就是说可以在一个bean在创建的时候先创建依赖的bean,在上面的代码注释中已经很详细的说明了这个作用,这边来做一个例子
@Component
public class X {
public X(){
System.out.println("Create X ");
}
}
@Component
public class Y {
@Autowired
private X x;
public Y(){
System.out.println("Create Y");
}
}
正常执行如下:
如果我修改下依赖,我要求X在创建的时候依赖Y
@Component
@DependsOn("y")
public class X {
public X(){
System.out.println("Create X ");
}
}
输出的效果就是先与Y创建,再创建X,那么spring源码中对@DependsOn的循环依赖是什么呢?就是X依赖Y,而Y又依赖了X,这就导致了循环依赖,在@DependsOn中的循环依赖是没有办法解决的,spring会直接报错,比如:
@Component
@DependsOn("x")
public class Y {
@Autowired
private X x;
public Y(){
System.out.println("Create Y");
}
}
这个错翻下上面的处理DependsOn的时候有这个异常的 ,所以spring是没有办法处理@DependsOn的循环依赖的;
下面我们看下DependsOn的源码:
protected boolean isDependent(String beanName, String dependentBeanName) {
//dependentBeanMap存放的是我当前beanName被那些beanName依赖了,这个是在扫描阶段完成的
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
//这里是怕你传入的是bean的别名,所以这里是处理别名的
String canonicalName = canonicalName(beanName);
//获取beanName被依赖的beanNames集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
//如果被我依赖的beanNames中还包含了我,那么就是循环依赖
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
// 如果上面的条件不满足,就循环递归去检查
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
到这里,初始化过程就差不多了,getBean里面的最难也是最核心的createBean的在后面的笔记中去记录,这篇笔记就到这里了。
上一篇: php 获取一个月第一天与最后一天的代码_PHP教程
下一篇: 在Ubuntu中安装PHP