Spring Bean加载过程 FactoryBean对象加载

FactoryBean是一种特殊的Bean,作用就是创建我们需要的Bean对象,如果对象的创建过程比较复杂,或者要为接口创建动态代理对象等,都可以用FactoryBean来实现

FactoryBean是一种典型的工厂方法模式的运用,在整合框架上面用的比较多,比如整合Mybatis中的MapperFactoryBean

demo

@Component
public class FactoryBeanDemo implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new User();
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

下面进入源码
ApplicationContext调用refresh方法,倒数第二步,加载bean对象

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// 加载bean对象
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				// ...
			}

			finally {
				// ...
			}
		}
	}

最后执行到DefaultListableBeanFactory.preInstantiateSingletons方法

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

	public void preInstantiateSingletons() throws BeansException {
		// ...
		// 把解析到的beanNames一个一个的拿出来遍历
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 判断是不是工厂bean
				if (isFactoryBean(beanName)) {
                    // 获取工厂bean,& + beanName
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
                        // 只有实现了SmartFactoryBean 并且重写了isEagerInit方法,才会加载真正                                                    的bean,调用getObject方法
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				// 不是FactoryBean走这里
				else {
					getBean(beanName);
				}
			}
		}

		// ...
	}

判断是不是FactoryBean

public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
	String beanName = transformedBeanName(name);
	// 先去单例池中找,能找到就直接返回是不是实现了FactoryBean接口
    Object beanInstance = getSingleton(beanName, false);
	if (beanInstance != null) {
		return (beanInstance instanceof FactoryBean);
	}
	// No singleton instance found -> check bean definition.
	if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
		// No bean definition found in this factory -> delegate to parent.
		return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
	}
	// 单例池找不到,直接通过BeanDefinition判断是不是FactoryBean
	return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
	}

从前面DefaultListableBeanFactory.preInstantiateSingletons方法中可以看出,工厂bean调用getBean方法传的是 & + beanName ,在我这个demo里是:&factoryBeanDemo

再来看看getBean方法,最终会调到doGetBean方法

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		// 把&factoryBeanDemo 又转换成factoryBeanDemo,以factoryBeanDemo把对象加载到单例池中
		String beanName = transformedBeanName(name);
		Object beanInstance;

		// 从单例池拿对象,第一次肯定拿不到
		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 + "'");
				}
			}
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// ...
			try {
				// ...

				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 创建实例,和正常创建实例一样,beanName = factoryBeanDemo
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							
							destroySingleton(beanName);
							throw ex;
						}
					});
					// 获取真正的对象
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// ...
			}
			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);
	}

返回真正对象的方法

// 本例中name 传入&factoryBeanDemo, beanName传入factoryBeanDemo
protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 这个判断就是判断name是不是&开头,这里为true,直接返回传入的FactoryBeanDemo对象
		// 所以ApplicationContext调用refresh方法时触发的对象加载,并不会调用FactoryBean的getObject方法
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			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.
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

可以看出,ApplicationContext调用refresh方法时触发的对象加载,传入& + beanName,然后进到方法后,又会截取掉&,执行的流程和普通getBean流程一样,最后把beanName对应的FacotyBean对象放入单例池中,本例中就是singletonObjects.put(“factoryBeanDemo” :FactoryBeanDemo对象)

到此ApplicationContext.refresh创建工厂对象的过程就走完了

可以看到,到目前为止还没有调用FactoryBean.getObject方法,那我们怎么拿到getObject返回的对象呢?
答案是:再次调用getBean方法并且不加"&"前缀,如本例中调用getBean(“factoryBeanDemo”)

回到doGetBean方法

// name = factoryBeanDemo
protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

	String beanName = transformedBeanName(name);
	Object beanInstance;

	// 这次从单例池能拿到对象,不过是FactoryBean对象
	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.getObject获取需要的对象
		beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
	
	// ...
}

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 不是以&开头,不会走这个if
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		// 
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			// 从factoryBeanObjectCache取对象,现在还取不到
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 走这里获取FactoryBean.getObject的对象
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
	if (factory.isSingleton() && containsSingleton(beanName)) {
		// 是单例,加锁创建
		synchronized (getSingletonMutex()) {
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
				// 这个object已经是调用FactoryBean.getObject获得的对象
				object = doGetObjectFromFactoryBean(factory, beanName);
				// 判断缓存里是否有,感觉这个判断是不是放在doGetObjectFromFactoryBean方法前更好?
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else {
					if (shouldPostProcess) {
						if (isSingletonCurrentlyInCreation(beanName)) {
							// Temporarily return non-post-processed object, not storing it yet..
							return object;
						}
						beforeSingletonCreation(beanName);
						try {
							// 执行beanPostProcessor的后置处理方法
							object = postProcessObjectFromFactoryBean(object, beanName);
						}
						catch (Throwable ex) {
							throw new BeanCreationException(beanName,
									"Post-processing of FactoryBean's singleton object failed", ex);
						}
						finally {
							afterSingletonCreation(beanName);
						}
					}
					if (containsSingleton(beanName)) {
						// 存入缓存中,下次就能直接拿到了
						this.factoryBeanObjectCache.put(beanName, object);
					}
				}
			}
			return object;
		}
	}
	else {
		// 不是单例,每次都重新创建一下
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (shouldPostProcess) {
			try {
				object = postProcessObjectFromFactoryBean(object, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
			}
		}
		return object;
	}
}


private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
	Object object;
	try {
		if (System.getSecurityManager() != null) {
			AccessControlContext acc = getAccessControlContext();
			try {
				object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			// 这里调用factory.getObject()获得真正需要的对象
			object = factory.getObject();
		}
	}
	catch (FactoryBeanNotInitializedException ex) {
		throw new BeanCurrentlyInCreationException(beanName, ex.toString());
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
	}

	// Do not accept a null value for a FactoryBean that's not fully
	// initialized yet: Many FactoryBeans just return null then.
	if (object == null) {
		if (isSingletonCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(
					beanName, "FactoryBean which is currently in creation returned null from getObject");
		}
		object = new NullBean();
	}
	return object;
}

总结一下流程:

第一次ApplicationContext.refresh创建FactoryBean对象

  1. 判断bean是不是FactoryBean
  2. 如果是FactoryBean,调用getBean("&" + beanName)加载单例bean
  3. doGetBean方法先把beanName截去"&",然后执行正常加载bean的过程,最后把FactoryBean放入单例池,key是截去"&"的beanName
  4. 不会调用FactoryBean的getObject方法,而是直接返回FactoryBean对象

第二次getBean(beanName)

  1. 去单例池拿FactoryBean对象
  2. 拿到对象,先去factoryBeanObjectCache缓存里看是否有FactoryBean.getObject方法创建的对象
  3. 没有就调用FactoryBean.getObject方法创建一个对象
  4. 调用beanPostProcessor的后置处理方法,应该主要是为了看看需不需要生成动态代理对象
  5. 返回真正的对象

注意:可以看出通过FactoryBean.getObject获得的对象没有经历完整的Bean创建流程,只是会调用beanPostProcessor的后置处理方法,前置处理等方法都不会调用,这一点需要留意

FactoryBean是Spring框架中的一个接口,它提供了一种在容器中创建bean的方式。使用FactoryBean可以实现延迟加载,即在需要的时候才创建bean实例。下面是一个简单的示例: 1. 创建一个工厂类,实现FactoryBean接口: ``` public class MyBeanFactory implements FactoryBean<MyBean> { private boolean lazyInit = true; @Override public MyBean getObject() throws Exception { System.out.println("getObject() called"); return new MyBean(); } @Override public Class<?> getObjectType() { return MyBean.class; } @Override public boolean isSingleton() { return true; } public boolean isLazyInit() { return lazyInit; } public void setLazyInit(boolean lazyInit) { this.lazyInit = lazyInit; } } ``` 2. 配置bean: ``` <bean id="myBeanFactory" class="com.example.MyBeanFactory"> <property name="lazyInit" value="true"/> </bean> ``` 3. 在需要使用MyBean的地方,通过ApplicationContext获取实例: ``` ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyBean myBean = (MyBean) context.getBean("myBeanFactory"); ``` 在这个例子中,当ApplicationContext获取MyBean实例时,如果lazyInit属性为true,则不会立即创建MyBean实例,而是在第一次调用getObject()方法时才会创建。如果lazyInit属性为false,则在容器启动时就会创建MyBean实例。 使用FactoryBean可以实现延迟加载,避免在启动时就创建所有的bean,提高了应用程序的启动速度。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值