• Spring源码之FactoryBean的实现


    https://zhuanlan.zhihu.com/p/97005407
    https://blog.csdn.net/qq_35634181/article/details/104507465

    总结

    1. FactoryBean的对象会先在createWebServer时,创建BeanWrapper,并放到factoryBeanInstanceCache缓存中
    2. 在预实例化时,走FactoryBean逻辑,调用getBean去执行属性注入、初始化过程(此时对象实例化直接从factoryBeanInstanceCache缓存中取)
    3. 完成FactoryBean的实现类初始化
    4. 调用实现类的getObject方法,从而对工厂中类进行功能增强

    FactoryBean(实现类)的初始化

    初始化入口依然是AbstractApplicationContext#finishBeanFactoryInitialization() ,走到DefaultListableBeanFactory类preInstantiateSingletons方法时,和普通bean逻辑不同,执行以下代码:

    @Override
    public void preInstantiateSingletons() throws BeansException {
    
    
    	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
    	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
    	// Trigger initialization of all non-lazy singleton beans...
    	for (String beanName : beanNames) {
    		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    		    //FactoryBean的初始化执行入口
    			if (isFactoryBean(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());
    					}
    					else {
    						isEagerInit = (factory instanceof SmartFactoryBean &&
    								((SmartFactoryBean<?>) factory).isEagerInit());
    					}
    					if (isEagerInit) {
    						getBean(beanName);
    					}
    				}
    			}
    			else {
    			    //普通bean的执行入口
    				getBean(beanName);
    			}
    		}
    	}
    }	
    

    调用Object bean = getBean(FACTORY_BEAN_PREFIX + beanName),后面基本和普通bean的初始化一致

    其中不同有:instanceWrapper不为null,是createWebServer时放入factoryBeanInstanceCache中的

    if (mbd.isSingleton()) {
    	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    

    将FactoryBean实现类放入缓存调用链为:

    SpringApplication#run() --> SpringApplication#refreshContext() --> SpringApplication#refresh() -->ServletWebServerApplicationContext#refresh() --> AbstractApplicationContext#refresh() --> AbstractApplicationContext#onRefresh() --> ServletWebServerApplicationContext#createWebServer() --> ServletWebServerApplicationContext#getWebServerFactory() --> DefaultListableBeanFactory#getBeanNamesForType() --> DefaultListableBeanFactory#doGetBeanNamesForType() --> AbstractBeanFactory#isTypeMatch() --> AbstractAutowireCapableBeanFactory#getTypeForFactoryBean() --> AbstractAutowireCapableBeanFactory#getSingletonFactoryBeanForTypeCheck()

    mbd为:

    // Generics potentially only match on the target class, not on the proxy...
    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    

    bw为:

    Object instance;
    try {
    	// Mark this bean as currently in creation, even if just partially.
    	beforeSingletonCreation(beanName);
    	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    	instance = resolveBeforeInstantiation(beanName, mbd);
    	if (instance == null) {
    		bw = createBeanInstance(beanName, mbd, null);
    		instance = bw.getWrappedInstance();
    	}
    }
    catch (BeanCreationException ex) {
    	......
    }
    finally {
    	// Finished partial creation of this bean.
    	afterSingletonCreation(beanName);
    }
    

    FactoryBean为:

    FactoryBean<?> fb = getFactoryBean(beanName, instance);
    if (bw != null) {
    	this.factoryBeanInstanceCache.put(beanName, bw);
    }
    

    获取FactoryBean实现类(非工厂)的过程

    如(此时beanName前面没有&):

    Object factoryBeanTest = context.getBean("factoryBeanTest");
    

    会先在AbstractBeanFactory#doGetBean()中执行:

    protected <T> T doGetBean(
    		String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    		throws BeansException {
    
    
    	// Eagerly check singleton cache for manually registered singletons.
    	Object sharedInstance = getSingleton(beanName);
    	if (sharedInstance != null && args == null) {
    		......
    		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    	}
    }
    

    执行getObjectForBeanInstance方法:

    protected Object getObjectForBeanInstance(
    		Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
        ......
        
    	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;
    }
    

    调用getObjectFromFactoryBean,再调用doGetObjectFromFactoryBean方法:

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    	if (factory.isSingleton() && containsSingleton(beanName)) {
    		synchronized (getSingletonMutex()) {
    		    //object为null
    			Object object = this.factoryBeanObjectCache.get(beanName);
    			if (object == null) {
    				object = doGetObjectFromFactoryBean(factory, beanName);
    				
    				......
    			}
    		}
    	}
    }	
    

    最后调用实际FactoryBean实现类的getObject方法,完成工厂类的自定义功能增强

    private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    	Object object;
    	try {
    		if (System.getSecurityManager() != null) {
    			......
    		}
    		else {
    		    //去执行实际实现类的getObject方法
    			object = factory.getObject();
    		}
    	}
    
    	return object;
    }
    

    通过FactoryBean.getObject方式

    如:

    FactoryBean bean = (FactoryBean)context.getBean("&factoryBeanTest");
    CustomTask customTask = (CustomTask)bean.getObject();
    

    会通过AbstractBeanFactory#doGetBean()直接返回bean

    protected <T> T doGetBean(
    		String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    		throws BeansException {
    
    	// Eagerly check singleton cache for manually registered singletons.
    	//此时一级缓存singletonObjects中有数据
    	Object sharedInstance = getSingleton(beanName);
    	if (sharedInstance != null && args == null) {
    		......
    		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    	}
    

    调用getObjectForBeanInstance,返回beanInstance

    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.
    	//此时为true
    	if (BeanFactoryUtils.isFactoryDereference(name)) {
    		......
    		if (mbd != null) {
    			mbd.isFactoryBean = true;
    		}
    		return beanInstance;
    	}
    }
    

    其后便是调用FactoryBean实现类的getObject方法,完成工厂类的自定义功能增强

    FactoryBean实现示例:

    @Component
    public class FactoryBeanTest implements FactoryBean {
        @Override
        public Object getObject() throws Exception {
            //一些自定义功能
            ......
            return new CustomTask();
        }
    
        @Override
        public Class<?> getObjectType() {
            return CustomTask.class;
        }
    }
    

    springboot中调用例子:

    @RestController
    public class TestController {
    
        @Autowired
        private AnnotationConfigServletWebServerApplicationContext context;
    
        @RequestMapping("/test")
        public String test() throws Exception {
    
            Object factoryBeanTest = context.getBean("factoryBeanTest");
            System.out.println(factoryBeanTest.toString());
    
            FactoryBean bean = (FactoryBean)context.getBean("&factoryBeanTest");
            CustomTask customTask = (CustomTask)bean.getObject();
            customTask.execute();
            return bean.getObject().toString();
        }
    }
    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出。
  • 相关阅读:
    正在找工作/打算找工作的看过来!
    xx星空面试题
    买的书不少,看的书不多,这是病
    公司那么多 我想去面面
    Android设备直接运行java项目?还杀不死?
    node-sass安装失败 解决办法(linux和window)
    Vue + element控制鼠标右键菜单
    Vue.js中Promise、异步、同步、定时器
    选择器&伪类选择器
    根据城市名称获取对应的省份名称
  • 原文地址:https://www.cnblogs.com/caozibiao/p/13971530.html
Copyright © 2020-2023  润新知