前提
BeanFactory和FactoryBean在学习Spring源码之前总是傻傻分不清,搞不懂两者的区别,这次学习Spring源码的过程,感觉自己开窍了,整理下相关点,希望可以帮助需要的朋友。
几个概念要分清楚
何为Bean?
类比的方式 Java Object 等同于 Spring Bean。Bean就是Spring中管理的对象。所以无论是BeanFactory还是FactoryBean,都是为了操作Spring中的对象。之后在怎么区分两者呢,Java中常讲的命名要规范,那Spring源码命名绝对是典范,BeanFactory—— bean工厂,FactoryBean——工厂bean,两者英译汉的侧重点,一个是工厂,另一个bean而已。
BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是 Spring IOC 所遵守的最底层和最基本的编程规范。在 Spring 代码中, BeanFactory 只是个接口,并不是 IOC 容器的具体实现,但是 Spring 容器给出了很多种实现,如 DefaultListableBeanFactory 、XmlBeanFactory等。
在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的,同样Factory也是需要接受BeanFactory的管理。
FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似 、 ApplicationContext 等,都是附加了某种功能的实现。一个Bean如果实现了FactoryBean接口,那么根据该Bean的名称获取到的实际上是getObject()返回的对象,而不是这个Bean自身实例,如果要获取这个Bean自身实例,那么需要在名称前面加上'&'符号。下方简单附一个FactoryBean的使用方式
@Component
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new User();
}
@Override
public Class> getObjectType() {
return User.class;
}
}
System.out.println(context.getBean("myFactroyBean")); //User
System.out.println(context.getBean("&myFactroyBean")); //MyFactroyBean
上篇文章说每一个bean都一个对应的BeanDefinition,其中定义bean的相关属性,再加上注册器就可以实现Bean的创建,那么为什么还要有一个FactoryBean同样可以用来创建Bean呢?
在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在
FactoryBean就相当于Spring提供外界的一个暴露点,通过它完整复杂Bean的实例化。
// org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//获取bean真正的名称
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//从单例对象池拿到bean实例
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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 以下逻辑省略,如有需要自行查看源码
}
transformedBeanName(name)是为了获取Bean真正的名称,它会去掉name前面的'&'
,而getSingleton(beanName)是从父类容器singletonObjects中取的这个Bean的实例。在Spring中还有很多这样的容器,比如DefaultListableBeanFactory中的beanDefinitionMap,它就是的IOC容器真正保存Bean的地方,它是一个CurrentHashMap。类似的还有FactoryBeanRegistrySupport中的factoryBeanObjectCache等。
拿到sharedInstance后,后面的一大堆操作做了单例、多例等判断,最终会走到this.getObjectForBeanInstance(),关键部分就在这个方法中,进入方法代码。
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是否不为空且以&开头
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.
//判断的是beanInstance是否属于FactoryBean或其子类的实例
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;
}
上述逻辑关键点 beanInstance instanceof FactoryBean
和BeanFactoryUtils.isFactoryDereference(name)。
如果beanInstance不属于FactoryBean或其子类的实例,或者name是以&
开头就直接返回实例对象beanInstance,否则进入到if分支中。分支中重点
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
具体逻辑如下
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 = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
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 {
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;
}
}
这段逻辑中大概的意思就是目的是从factoryBeanObjectCache中获得FactoryBean,无论是否能拿到if else中逻辑都会执行object = doGetObjectFromFactoryBean(factory, beanName);
private Object doGetObjectFromFactoryBean(final FactoryBean> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction
关键点
object = AccessController.doPrivileged((PrivilegedExceptionAction
这个factory就是我们传入的beanInstance
实例。绕了这么一大圈,getBean方法返回的居然是我们实现FactoryBean接口定义的getObject方法。这刚好和上方的描述相呼应了。
额外解释下 factoryBeanObjectCache 是什么?
/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
private final Map factoryBeanObjectCache = new ConcurrentHashMap<>(16);
通过这个定义和源码中注释可以得知 factoryBeanObjectCache中存储的FactoryBean,在getObjectForBeanInstance()中有段逻辑
object = getCachedObjectForFactoryBean(beanName);
/**
* Obtain an object to expose from the given FactoryBean, if available
* in cached form. Quick check for minimal synchronization.
* @param beanName the name of the bean
* @return the object obtained from the FactoryBean,
* or {@code null} if not available
*/
@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
如果以&
开头就直接返回实例对象beanInstance,beanInstance则是从factoryBeanObjectCache中获取的,由此也知道FactoryBean本身并不存储到单例对象池中,获取本身为需要加&用于区分。
主要介绍BeanFactory和FactoryBean在命名上区分,在Spring中不同的作用,以及FactoryBean的实验原理。FactoryBean在Spring中存在的意义为了解决配置方式装配bean灵活性是受限的问题,通过编码得到一个简单的方案。
关于FactoryBean的使用场景,特别像代理模式的实现方案,借助FactoryBean创建代理对象在原对象基础上处理其他内容。那么代理对象和工厂模式,装饰模式又有什么不同呢?之后的文章中慢慢解答,请关注哈!