小言_互联网的博客

【源码Spring系列】——彻底搞懂BeanFactory和FactoryBean

325人阅读  评论(0)

前提

        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的使用方式


  
  1. @Component
  2. public class MyFactoryBean implements FactoryBean {
  3. @Override
  4. public Object getObject() throws Exception {
  5. return new User();
  6. }
  7. @Override
  8. public Class<?> getObjectType() {
  9. return User.class;
  10. }
  11. }
  12. System.out.println(context.getBean( "myFactroyBean")); //User
  13. 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实现原理


  
  1. // org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
  2. protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  3. @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  4. //获取bean真正的名称
  5. final String beanName = transformedBeanName(name);
  6. Object bean;
  7. // Eagerly check singleton cache for manually registered singletons.
  8. //从单例对象池拿到bean实例
  9. Object sharedInstance = getSingleton(beanName);
  10. if (sharedInstance != null && args == null) {
  11. if (logger.isTraceEnabled()) {
  12. if (isSingletonCurrentlyInCreation(beanName)) {
  13. logger.trace( "Returning eagerly cached instance of singleton bean '" + beanName +
  14. "' that is not fully initialized yet - a consequence of a circular reference");
  15. }
  16. else {
  17. logger.trace( "Returning cached instance of singleton bean '" + beanName + "'");
  18. }
  19. }
  20. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  21. }
  22. // 以下逻辑省略,如有需要自行查看源码
  23. }

transformedBeanName(name)是为了获取Bean真正的名称,它会去掉name前面的'&',而getSingleton(beanName)是从父类容器singletonObjects中取的这个Bean的实例。在Spring中还有很多这样的容器,比如DefaultListableBeanFactory中的beanDefinitionMap,它就是的IOC容器真正保存Bean的地方,它是一个CurrentHashMap。类似的还有FactoryBeanRegistrySupport中的factoryBeanObjectCache等。

拿到sharedInstance后,后面的一大堆操作做了单例、多例等判断,最终会走到this.getObjectForBeanInstance(),关键部分就在这个方法中,进入方法代码。


  
  1. protected Object getObjectForBeanInstance(
  2. Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
  3. // Don't let calling code try to dereference the factory if the bean isn't a factory.
  4. //判断name是否不为空且以&开头
  5. if (BeanFactoryUtils.isFactoryDereference(name)) {
  6. if (beanInstance instanceof NullBean) {
  7. return beanInstance;
  8. }
  9. if (!(beanInstance instanceof FactoryBean)) {
  10. throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
  11. }
  12. if (mbd != null) {
  13. mbd.isFactoryBean = true;
  14. }
  15. return beanInstance;
  16. }
  17. // Now we have the bean instance, which may be a normal bean or a FactoryBean.
  18. // If it's a FactoryBean, we use it to create a bean instance, unless the
  19. // caller actually wants a reference to the factory.
  20. //判断的是beanInstance是否属于FactoryBean或其子类的实例
  21. if (!(beanInstance instanceof FactoryBean)) {
  22. return beanInstance;
  23. }
  24. Object object = null;
  25. if (mbd != null) {
  26. mbd.isFactoryBean = true;
  27. }
  28. else {
  29. object = getCachedObjectForFactoryBean(beanName);
  30. }
  31. if (object == null) {
  32. // Return bean instance from factory.
  33. FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
  34. // Caches object obtained from FactoryBean if it is a singleton.
  35. if (mbd == null && containsBeanDefinition(beanName)) {
  36. mbd = getMergedLocalBeanDefinition(beanName);
  37. }
  38. boolean synthetic = (mbd != null && mbd.isSynthetic());
  39. object = getObjectFromFactoryBean(factory, beanName, !synthetic);
  40. }
  41. return object;
  42. }

上述逻辑关键点 beanInstance instanceof FactoryBeanBeanFactoryUtils.isFactoryDereference(name)。如果beanInstance不属于FactoryBean或其子类的实例,或者name是以&开头就直接返回实例对象beanInstance,否则进入到if分支中。分支中重点

object = getObjectFromFactoryBean(factory, beanName, !synthetic);

具体逻辑如下


  
  1. protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
  2. if (factory.isSingleton() && containsSingleton(beanName)) {
  3. synchronized (getSingletonMutex()) {
  4. Object object = this.factoryBeanObjectCache.get(beanName);
  5. if (object == null) {
  6. object = doGetObjectFromFactoryBean(factory, beanName);
  7. // Only post-process and store if not put there already during getObject() call above
  8. // (e.g. because of circular reference processing triggered by custom getBean calls)
  9. Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
  10. if (alreadyThere != null) {
  11. object = alreadyThere;
  12. }
  13. else {
  14. if (shouldPostProcess) {
  15. if (isSingletonCurrentlyInCreation(beanName)) {
  16. // Temporarily return non-post-processed object, not storing it yet..
  17. return object;
  18. }
  19. beforeSingletonCreation(beanName);
  20. try {
  21. object = postProcessObjectFromFactoryBean(object, beanName);
  22. }
  23. catch (Throwable ex) {
  24. throw new BeanCreationException(beanName,
  25. "Post-processing of FactoryBean's singleton object failed", ex);
  26. }
  27. finally {
  28. afterSingletonCreation(beanName);
  29. }
  30. }
  31. if (containsSingleton(beanName)) {
  32. this.factoryBeanObjectCache.put(beanName, object);
  33. }
  34. }
  35. }
  36. return object;
  37. }
  38. }
  39. else {
  40. Object object = doGetObjectFromFactoryBean(factory, beanName);
  41. if (shouldPostProcess) {
  42. try {
  43. object = postProcessObjectFromFactoryBean(object, beanName);
  44. }
  45. catch (Throwable ex) {
  46. throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
  47. }
  48. }
  49. return object;
  50. }
  51. }

这段逻辑中大概的意思就是目的是从factoryBeanObjectCache中获得FactoryBean,无论是否能拿到if else中逻辑都会执行object = doGetObjectFromFactoryBean(factory, beanName);


  
  1. private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
  2. throws BeanCreationException {
  3. Object object;
  4. try {
  5. if (System.getSecurityManager() != null) {
  6. AccessControlContext acc = getAccessControlContext();
  7. try {
  8. object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
  9. }
  10. catch (PrivilegedActionException pae) {
  11. throw pae.getException();
  12. }
  13. }
  14. else {
  15. object = factory.getObject();
  16. }
  17. }
  18. catch (FactoryBeanNotInitializedException ex) {
  19. throw new BeanCurrentlyInCreationException(beanName, ex.toString());
  20. }
  21. catch (Throwable ex) {
  22. throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
  23. }

关键点

object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);

这个factory就是我们传入的beanInstance实例。绕了这么一大圈,getBean方法返回的居然是我们实现FactoryBean接口定义的getObject方法。这刚好和上方的描述相呼应了。

额外解释下 factoryBeanObjectCache 是什么?


  
  1. /** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
  2. private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>( 16);

通过这个定义和源码中注释可以得知 factoryBeanObjectCache中存储的FactoryBean,在getObjectForBeanInstance()中有段逻辑


  
  1. object = getCachedObjectForFactoryBean(beanName);
  2. /**
  3. * Obtain an object to expose from the given FactoryBean, if available
  4. * in cached form. Quick check for minimal synchronization.
  5. * @param beanName the name of the bean
  6. * @return the object obtained from the FactoryBean,
  7. * or {@code null} if not available
  8. */
  9. @Nullable
  10. protected Object getCachedObjectForFactoryBean(String beanName) {
  11. return this.factoryBeanObjectCache.get(beanName);
  12. }

如果以&开头就直接返回实例对象beanInstance,beanInstance则是从factoryBeanObjectCache中获取的,由此也知道FactoryBean本身并不存储到单例对象池中,获取本身为需要加&用于区分。

       主要介绍BeanFactory和FactoryBean在命名上区分,在Spring中不同的作用,以及FactoryBean的实验原理。FactoryBean在Spring中存在的意义为了解决配置方式装配bean灵活性是受限的问题,通过编码得到一个简单的方案。

      关于FactoryBean的使用场景,特别像代理模式的实现方案,借助FactoryBean创建代理对象在原对象基础上处理其他内容。那么代理对象和工厂模式,装饰模式又有什么不同呢?之后的文章中慢慢解答,请关注哈!


转载:https://blog.csdn.net/jiadajing267/article/details/106505581
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场