zoukankan      html  css  js  c++  java
  • spring源码分析——BeanFactory与FactoryBean的区别

      BeanFactory是spring容器的顶层bean工厂,它提供了从容器获取bean,判断是否存在bean的一些简单方法。FactoryBean是创建

    Bean对象的一种方式,如果我们不希望通过扫描注册,就可以使用这种方式注册Bean。

    一:BeanFactory接口

     这个接口类提供getBean,containsBean,isSingleton,isPrototype等简单的操作

    public interface BeanFactory {
    
    	 
    	String FACTORY_BEAN_PREFIX = "&";
    
    
    	Object getBean(String name) throws BeansException;
    
    	 
    	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
    
    	 
    	Object getBean(String name, Object... args) throws BeansException;
    
    	 
    	<T> T getBean(Class<T> requiredType) throws BeansException;
    
    	 
    	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
     
    	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
    
    	 
    	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
    
    	 
    	boolean containsBean(String name);
    
    	 
    	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    
    	 
    	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    
    	 
    	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    
    	 
    	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    
    	
    	@Nullable
    	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    
    	 
    	String[] getAliases(String name);
    
    }  

    我们spring容器拉起的过程中,使用它的子类比较多,

    快捷键Ctrl + alt + u 可以查询类的继承关系

    而ApplicationContext与BeanFactory的关系,就是ApplicatationContext在BeanFactroy提供功能的基础上做了一些扩展,比如国际化的操作,解析等

    写个测试类,测试一下拿到的beanFactory对象:

    @Component
    public class BeanFactoryTest implements BeanFactoryAware {
    
    	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    		System.out.println("beanFactory: "+beanFactory);
    		System.out.println("student: "+beanFactory.getBean("student"));
    	}
    
    }
    

      

     实际注入的是DefaultListableBeanFactory这个工厂对象,通过这个工厂容器可以拿到bean对象。

    二:FactoryBean接口

    实现FactoryBean接口,这个接口内有三个方法,getObject,实际创建的对象,getObjectType对象类型,isSingleton是否单例

    @Component
    public class MyFactoryBean implements FactoryBean<User> {
    
    	public User getObject() throws Exception {
    		return new User();
    	}
    
    	public Class<?> getObjectType() {
    		return User.class;
    	}
    
    	public boolean isSingleton() {
    		return true;
    	}
    }
    

      

    测试代码:

    通过运行结果可以看出,beanName为myFactoryBean时,实际返回的是getObject方法的对象,如果想要获取MyFactoryBean本身的对象,需要加上&符号 

    下面我们来分析一下源码怎么实现的?

    先来看一下预实例化的时候,判断是否是FactoryBean,

     

     判断是否是FactoryBean接口的实例,很显然,MyFactoryBean是的,然后调用getBean实例化这个对象,beanName前面加上&,就是实例化自身的对象

    实例化完成后

     直接返回这个实例对象,只有是FactoryBean对象,同时没有&符合时,才会去调用getObject方法,

    看一下没有&符号的getBean:

    因为已经预实例化,所以缓存中存在MyFactoryBean这个对象,走到getObjectForBeanInstance这个方法

     

     

    调用getObject方法获取真实的对象,这样实际上返回的是User对象。

    如果前面加上&符号时,返回的是本身的对象,我们来分析一下

     因为是以&开头的,所以直接返回这个实例对象,而没有去调用getObject方法。

     

     

     以上便是获取FactoryBean本身对象的过程。

    上面都是单例的情况,如果isSingleton是false呢

     

     如果是isSingleton为false或者母体类就是非单例,那么直接getObject返回,跟缓存没有关系

     以上就是从源码层面分析了FactoryBean的使用以及如何实现,这个接口在mybatis等和spring整合的框架中应用比较多。

  • 相关阅读:
    sublime text3快捷键
    SublimeText3追踪函数工具CTags设置及使用
    mysql的表锁
    ESXI vSphere如何设置虚拟机开机自启动
    gitee支持的开源许可证
    keepalive安装部署踩坑参考
    《牧神记》中诗词大全,有的可能是作者瞎编的
    定位Linux服务器SSH敲命令响应慢的问题
    Crypto-JS——Uncaught Error: Malformed UTF-8 data
    VUE——vue中组件之间的通信方式有哪些
  • 原文地址:https://www.cnblogs.com/warrior4236/p/13229412.html
Copyright © 2011-2022 走看看