• Spring - FactoryBean扩展接口


    在这里插入图片描述


    Pre

    Spring Boot - 扩展接口一览

    在这里插入图片描述

    org.springframework.beans.factory.FactoryBean

    
    package org.springframework.beans.factory;
    
    import org.springframework.lang.Nullable;
    
    
    public interface FactoryBean<T> {
    
    
    	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
    
    
    	@Nullable
    	T getObject() throws Exception;
    
    	
    	@Nullable
    	Class<?> getObjectType();
    
    	
    	default boolean isSingleton() {
    		return true;
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述

    一般情况下,Spring通过反射机制利用bean的class属性指定支线类去实例化bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在bean中提供大量的配置信息。

    配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。

    FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。

    从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean的形式

    在这里插入图片描述


    FactoryBean中的设计模式----工厂方法模式

    工厂方法模式是简单工厂模式的一种升级或者说是进一步抽象,它可以应用于更加复杂的场景,灵活性也更高。

    在简单工厂中,由工厂类进行所有的逻辑判断、实例创建;

    如果不想在工厂类中进行判断,可以为不同的产品提供不同的工厂,不同的工厂生产不同的产品,每一个工厂都只对应一个相应的对象,这就是工厂方法模式。

    Spring 中的 FactoryBean 就是这种思想的体现,FactoryBean 可以理解为工厂 Bean

    
    public interface FactoryBean<T> {
      T getObject()Class<?> getObjectType();
      boolean isSingleton();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我们定义一个类 ArtisanFactoryBean 来实现 FactoryBean 接口,主要是在 getObject 方法里 new 一个 Artisan对象。这样我们通过 getBean(id) 获得的是该工厂所产生的 Artisan 的实例,而不是 ArtisanFactoryBean本身的实例,像下面这样:

    BeanFactory bf = new ClassPathXmlApplicationContext("artisan.xml");
    Artisan  artisanBean = (Artisan) bf.getBean("artisanFactoryBean");
    
    • 1
    • 2

    在这里插入图片描述


    FactoryBean VS BeanFactory

    • BeanFactory,就是bean的工厂,主要是通过定位、加载、注册以及实例化来维护对象与对象之间的依赖关系,以此来管理bean

    • FactoryBean,bean的一种,顾名思义,它也可以用来生产bean,也实现了相应的工厂方法。

    • 一般来说,Bean是由BeanFactory生产,但FactoryBean的特殊之处就在于它也能生产bean。

    • 获取FactoryBean的方法是getBean("&"+beanName); 就是在beanName加个"&"前缀,若直接getBean(beanName),获取到的是FactoryBean通过getObject接口生成的Bean


    源码解析

    org.springframework.beans.factory.support.AbstractBeanFactory#getBean
    		  org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean	
    			  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
    
    • 1
    • 2
    • 3

    我们从 AbstractBeanFactory#doGetBean 梳理起来

     protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
    		/**
    		 * 通过name获取BeanName,这里不能使用name作为beanName:
    		 * 1. name可能是别名,通过方法转换为具体的实例名称
    		 * 2. name可能会以&开头,表明调用者想获取FactoryBean本身,而非FactoryBean创建bean
    		 *    FactoryBean 的实现类和其他的 bean 存储方式是一致的,即 ,
    		 *    beanName 中是没有 & 这个字符的。所以我们需要将 name 的首字符 & 移除,这样才能从
    		 *    缓存里取到 FactoryBean 实例。
    		 *
    		 */
    		final String beanName = transformedBeanName(name);
    		Object bean;
    
    		// 从缓存中获取bean
    		Object sharedInstance = getSingleton(beanName);
    
    		/*
    		 * 如果 sharedInstance = null,则说明缓存里没有对应的实例,表明这个实例还没创建。
    		 *( BeanFactory 并不会在一开始就将所有的单例 bean 实例化好,而是在调用 getBean 获取bean 时再实例化,也就是懒加载)。
    		 * getBean 方法有很多重载,比如 getBean(String name, Object... args),我们在首次获取
    		 * 某个 bean 时,可以传入用于初始化 bean 的参数数组(args),BeanFactory 会根据这些参数
    		 * 去匹配合适的构造方法构造 bean 实例。当然,如果单例 bean 早已创建好,这里的 args 就没有
    		 * 用了,BeanFactory 不会多次实例化单例 bean。
    		 */
    		if (sharedInstance != null && args == null) {
    			// 省略.....
    
    			/*
    			 * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果
    			 * sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的
    			 * bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回
    			 * 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
    			 */
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}
    
    		/*
    		 * 如果上面的条件不满足,则表明 sharedInstance 可能为空,此时 beanName 对应的 bean
    		 * 实例可能还未创建。这里还存在另一种可能,如果当前容器有父容器,beanName 对应的 bean 实例
    		 * 可能是在父容器中被创建了,所以在创建实例前,需要先去父容器里检查一下。
    		 */
    		else {
    			// BeanFactory 不缓存 Prototype 类型的 bean,无法处理该类型 bean 的循环依赖问题
                //判断是否存在循环依赖
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
    
    			// 如果 sharedInstance = null,则到父容器中查找 bean 实例
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			// ......
    
    		
    			try {
    				// 合并父 BeanDefinition 与子 BeanDefinition
    				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				checkMergedBeanDefinition(mbd, beanName, args);
    
    				// 检查是否有 dependsOn 依赖,如果有则先初始化所依赖的 bean
    				String[] dependsOn = mbd.getDependsOn();
    				// ......
    					
    				// 创建 bean 实例
    				if (mbd.isSingleton()) {
    
    					/*
    					 * 这里并没有直接调用 createBean 方法创建 bean 实例,而是通过
    					 * getSingleton(String, ObjectFactory) 方法获取 bean 实例。
    					 * getSingleton(String, ObjectFactory) 方法会在内部调用
    					 * ObjectFactory 的 getObject() 方法创建 bean,并会在创建完成后,
    					 * 将 bean 放入缓存中。
    					 */
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
    							return createBean(beanName, mbd, args);
    						}
    						catch (BeansException ex) {
    							destroySingleton(beanName);
    							throw ex;
    						}
    					});
    					
    					// 如果 bean 是 FactoryBean 类型,则调用工厂方法获取真正的 bean 实例。否则直接返回 bean 实例
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
    
    				// 创建 prototype 类型的 bean 实例
    				else if (mbd.isPrototype()) {
    					// ......
    				}
    
    
    				// 创建其他类型的 bean 实例
    				else {
    					// ......
    		}
    
    		// ......
    		return adaptBeanInstance(name, beanInstance, requiredType);
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    重点来了 getObjectForBeanInstance 。 在getObjectForBeanInstance方法,它主要完成对获取的Bean Instance进行检测是否为FactoryBean,如果是FactoryBean则通过工厂方法获取Bean以及初始化后处理


    protected Object getObjectForBeanInstance(
    			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
    		// 判断name是否为Bean FactoryBean的引用
    		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;
    		}
    
    		// beanInstance可能是普通的bena或者FactoryBean,如果是普通的Bean直接返回实例
    		if (!(beanInstance instanceof FactoryBean)) {
    			return beanInstance;
    		}
    		
    		// 如果是FactoryBean,使用FactoryBean来创建一个bean实例
    		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());
    			// 从FactoryBean中获取创建的Bean
    			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    		}
    		return object;
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    先看看

    	public static boolean isFactoryDereference(@Nullable String name) {
    		return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
    	}
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    FactoryBean创建的Bean的名称FactoryBean本身作为一个Bean在Spring容器中是用是否包含 & 前缀来区分的。

    继续往下来

    // 从FactoryBean中获取创建的Bean
    object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    
    • 1
    • 2
    org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
    
    • 1
    	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) {
    					// 通过factory.getObject获取
    					object = doGetObjectFromFactoryBean(factory, beanName);
    					
    					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)) {
    							//将获取到的对象放到factoryBeanObjectCache单例缓存map进行存储
    							this.factoryBeanObjectCache.put(beanName, object);
    						}
    					}
    				}
    				return object;
    			}
    		}
    		else {
    			// 非单例模式,直接通过factory.getObejct获取,然后再返回给用户
    			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;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    通过源码我们可以发现,无论是单例和非单例都会调用doGetObjectFromFactoryBean方法,那毫无疑问就是生成bean对象的方法:

    private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    		Object object;
    		try {
    			// 系统安全处理器不为空
    			if (System.getSecurityManager() != null) {
    				AccessControlContext acc = getAccessControlContext();
    				try {
    					// 也是调用 factory::getObject
    					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
    				}
    				catch (PrivilegedActionException pae) {
    					throw pae.getException();
    				}
    			}
    			else {
    				// 调用FactoryBean的getObject方法
    				object = factory.getObject();
    			}
    		}
    		catch (){
    
    
    		}
    		// ....
    
    		return object;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    OK , DONE

    在这里插入图片描述


    扩展示例

    package com.artisan.bootspringextend.testextends;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.SneakyThrows;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.context.annotation.Configuration;
    
    import javax.annotation.PostConstruct;
    
    /**
     * @author 小工匠
     * @version 1.0
     * @description: TODO
     * @date 2022/12/5 23:45
     * @mark: show me the code , change the world
     */
    
    @Slf4j
    public class ExtendFactoryBean2 {
        public static void main(String[] args) {
            DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
            BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
                    .genericBeanDefinition(UserServiceFactoryBean.class);
            definitionBuilder.addPropertyValue("username", "artisan");
            beanFactory.registerBeanDefinition("userService", definitionBuilder.getBeanDefinition());
    
    
            UserService userService = (UserService) beanFactory.getBean("userService");
            //artisan
            log.info(userService.getUsername());
    
    
            UserServiceFactoryBean userServiceFactoryBean = (UserServiceFactoryBean) beanFactory.getBean("&userService");
            //artisan
            log.info(userServiceFactoryBean.username);
        }
    
        public static class UserServiceFactoryBean implements FactoryBean<UserService> {
    
            @Setter
            private String username;
    
    
            @Override
            public UserService getObject() {
                UserService userService = new UserService();
                userService.setUsername(username);
                return userService;
            }
    
            @Override
            public Class<?> getObjectType() {
                return UserService.class;
            }
        }
    
        @Setter
        @Getter
        public static class UserService {
    
            private String username;
        }
    }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    定义一个UserServiceFactoryBean,用来生产UserService,将其注册到BeanFactory中,如果使用UserService对象,使用userServiceBean名称,
    如果想要获取原来的UserServiceFactoryBean对象,需要使用&userService的Bean名称,&这个前缀是Spring规定的,可以查看BeanFactory#FACTORY_BEAN_PREFIX常量

    00:05:24.692 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService'
    00:05:24.762 [main] INFO com.artisan.bootspringextend.testextends.ExtendFactoryBean2 - artisan
    00:05:24.762 [main] INFO com.artisan.bootspringextend.testextends.ExtendFactoryBean2 - artisan
    
    Process finished with exit code 0
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

  • 相关阅读:
    Zabbix
    SpringBoot整合Shiro(Java安全框架)案例(含源码)
    【JavaWeb】第三章 JavaScript基础
    如何使用 TypeScript 编写“ Hello World “程序
    最佳实践| 一文读懂《MongoDB 使用规范及最佳实践》原理
    LeetCode题目笔记——206. 反转链表
    Redis 如何实现数据不丢失的?
    从云AK泄露利用看企业特权管理
    vue实战——404页面模板001——男女手电筒动画
    nodejs安装及环境配置
  • 原文地址:https://blog.csdn.net/yangshangwei/article/details/128183117