揭秘Spring(一)之BeanFactory和FactoryBean

BeanFactory

BeanFactory和ApplicationContext是Spring中的两种容器。

BeanFactory默认采用延迟初始化策略,所以相对来说,容器启动较快,所需资源不多。

ApplicationContext间接继承自BeanFactory,增加国际化等高级功能,其管理的对象在容器启动后默认全部初始化完成,所以启动所需要资源较多,所需时间长

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";
    
    // 返回bean
    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    boolean containsBean(String var1);

    // 是否是单例bean
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    
    // 是否是原型bean
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    
    // bean的类
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    
    // bean的别名,XML种的id
    String[] getAliases(String var1);
}

在BeanFactory接口中,如果你熟悉Spring的配置文件的话,想必会看到很多熟悉的方法。

实际上,BeanFactory只负责定义如何访问查看容器内Bean的状态,那么Bean从哪里来的呢?这些比较复杂的问题就交给底下人去办好啦,DefaultListableBeanFactory是BeanFactory的一个间接子类,它实现了BeanFactory的一个子接口。同时,他还实现了BeanDefinitionRegistry,这个接口定义了Bean的注册逻辑。

这里首先要知道Bean在容器中的形式是BeanDefinition,BeanDefinition实例中包括了对象的所有信息,当被注入类向容器请求依赖对象时候,BeanFactory就会通过对应BeanDefinition中的信息返回一个实例。

可以把BeanFactory看成是图书馆,BeanDefinitionRegistry就是图书馆里边的书架,书就在书架上存放着,这里也就要求我们的图书馆只能有一个书架。每个BeanDefinition都要被放在BeanDefinitionRegistry中才能被容器管理。

至于BeanDefinition,一般是通过BeanDefinitionReader读取配置文件并映射成对应的BeanDefinition来生成的。

FactoryBean

FactoryBean其实就是个工厂Bean接口,本质上也还是个bean,它生成的以及提供给容器管理的正是它的getObject()方法所返回的bean

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    // 返回要生产的bean
    T getObject() throws Exception;

    // 返回生产的bean的Class
    Class<?> getObjectType();

    // 返回生产的bean是否是Singleton
    default boolean isSingleton() {
        return true;
    }
}

来看一下FactoryBean的使用

public class User implements FactoryBean {

    private int id;

    private String name;

    @Override
    public boolean isSingleton() {
        return false;
    }

    @Override
    public Object getObject() throws Exception {
        return new User(1,"fbb");
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
    // setter // getter // constructor
}

上边这个User实现FactoryBean,可以用来生产名字为 fbb 的user,接着把这个工厂Bean交给Spring管理

@Configuration
public class config {

    @Bean
    public User user(){
        return new User(100,"bbf");
    }
}

可以看到我们在容器中注册了名字为 bbf 的user

接着检验一下到底容器中最后提供的user的名字是什么

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringdemoApplication.class)
public class UserTest {

    @Autowired
    private  User user;

    @Test
    public void tt(){
        System.out.println(user.getName());
    }
}
fbb

最后可以看到,容器提供的user的名字其实还是fbb,即我们的工厂bean中提供的,因为我们从工厂方法中获得的bean一定是从getObject()这个方法中获得的~

总结

所以,我们大体上应该明白了,BeanFactory是容器,而FactoryBean则是工厂Bean,帮助我们定制实例化Bean,其实这何尝不是代理模式的一个应用,我们可以在getObject()那里再加一些别的逻辑,相当于搞了一层代理~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值