前提
BeanFactory和FactoryBean在学习Spring源码之前总是傻傻分不清,搞不懂两者的区别,这次学习Spring源码的过程,感觉自己开窍了,整理下相关点,希望可以帮助需要的朋友。
几个概念要分清楚
何为Bean?
类比的方式 Java Object 等同于 Spring Bean。Bean就是Spring中管理的对象。所以无论是BeanFactory还是FactoryBean,都是为了操作Spring中的对象。之后在怎么区分两者呢,Java中常讲的命名要规范,那Spring源码命名绝对是典范,BeanFactory—— bean工厂,FactoryBean——工厂bean,两者英译汉的侧重点,一个是工厂,另一个bean而已。
BeanFactory
BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是 Spring IOC 所遵守的最底层和最基本的编程规范。在 Spring 代码中, BeanFactory 只是个接口,并不是 IOC 容器的具体实现,但是 Spring 容器给出了很多种实现,如 DefaultListableBeanFactory 、XmlBeanFactory等。
在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的,同样Factory也是需要接受BeanFactory的管理。
FactoryBean
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过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。
FactoryBean就相当于Spring提供外界的一个暴露点,通过它完整复杂Bean的实例化。
FactoryBean实现原理
-
// org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
-
protected <T>
T doGetBean(final String name, @Nullable final Class<T> 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>) factory::getObject, acc);
-
}
-
catch (PrivilegedActionException pae) {
-
throw pae.getException();
-
}
-
}
-
else {
-
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);
-
}
关键点
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
这个factory就是我们传入的beanInstance
实例。绕了这么一大圈,getBean方法返回的居然是我们实现FactoryBean接口定义的getObject方法。这刚好和上方的描述相呼应了。
额外解释下 factoryBeanObjectCache 是什么?
-
/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
-
private
final Map<String, Object> 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创建代理对象在原对象基础上处理其他内容。那么代理对象和工厂模式,装饰模式又有什么不同呢?之后的文章中慢慢解答,请关注哈!
转载:https://blog.csdn.net/jiadajing267/article/details/106505581