[springboot注解 容器篇] FactoryBean

FactoryBean不是注解,但是使用它可以直接向容器中注册bean,所以这里也介绍一下

这里直接上例子,然后通过例子来讲解其实用。

例子

首先创建FactoryBean的实现类

// 这个类就不单独占用地方了,就写在这里了
public class Animal {
}

public class AnimalFactoryBean implements FactoryBean<Animal> {
    // 当调用getBean这样的方法从容器中后去bean时,就会调用这个方法
    // 非单例模式下调用getBean时,就会执行这个方法来创建bean
    // 单例模式下,会先先调用这个方法生成bean,然后放到容器中,在调用getBean时直接从容器中拿,因为不会在调用这个方法,多以就是单例了
    @Override
    public Animal getObject() throws Exception {
        System.out.println("获取bean....");
        return new Animal();
    }

    @Override
    public Class<?> getObjectType() {
        return Animal.class;
    }

    // 设置是否为单例,true:单例,容器中是保存一份;false:非单例,每次获取时都创建一个新的实例
    @Override
    public boolean isSingleton() {
        return true;
    }
}

然后,在配置类中将FactoryBean的实现类生成的bean放到容器中 

@Configuration // 相当于写了一个spring的xml配置文件
public class MyConfig {
    // 创建一个FactoryBean,虽然是将AnimalFactoryBean放到了容器中,但是当调用getBean时,获取的不是AnimalFactoryBean,而是会调用AnimalFactoryBean中的getObject方法生成的bean。具体看main方法给出的注释。    
    @Bean
    public AnimalFactoryBean animalFactoryBean(){
        return new AnimalFactoryBean();
    }
}

最后,从容器中获取bean,这里注意观察截图中【1】【2】标注,下面会有解说 

public class AppliactionRunner {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] names = applicationContext.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name); //【1】打印出容器中所有的bean名字,
        }

        //【2】getBean时会调用容器中animalFactgoryBean的getObjec,然后返回方法中生成的对象
        Object animalFactgoryBean = applicationContext.getBean("animalFactoryBean");
        System.out.println("bean的类型" + animalFactgoryBean.getClass());
    }
}

运行结果:

 上面我们就完成了一个FactoryBean的使用。它的作用就是可以让我们自定义bean的创建过程,如下场景:

//Animal是个接口    
@Override
    public Animal getObject() throws Exception {
        // return的都是Animal的实现类
        if(今天周一){
            return new 小狗(); 
        }
        if(今天周二){
            return new 小猫();
        }
    }

这样我们就可以自定义bean的创建过程,根据条件返回不同的bean,当然必须是返回一个接口的实现类才行。然后当调用getBean的时候,就可以获取到这里根据业务返回的不同的实现类了,然后再用接口接收一下就行了。

另外,大家可能注意到打印结果和main方法中标注了【1】【2】两个地方,这也是使用FactoryBean的要注意的地方。下面我说明一下:
当在配置类通过@Bean向容器放入我们写的FactoryBean的实现类后,这个Bean会被放到容器中,这个通过【1】处的打印可得知。但是,当我们通过getBean获取这个bean时,有意思的事情发生了,注意观察【2】打印的结果,这个我们获取到的bean确实Animal这个类,这就是FactoryBean的特点和作用,虽然放到容器中的时FactoryBean的实现了,但是当getBean获取bean时,会调用这个实现类中的getObject方法,然后把里面return的对象返回。这个一定要记住昂。

那么有人会说,如果我就想用getBean获取FactoryBean的实现类,也就是我们例子中的AnimalFactoryBean的对象怎么办呢,其实很简单,方法如下:

// 将【2】改成这么写就行,加个&就行了
Object animalFactgoryBean = applicationContext.getBean("&animalFactoryBean");

为什么&就会拿到FactoryBean本身的那个实现类的对象呢,这是BeanFactory这个接口的作用,看源码
 

 这里定义了一个&,如果使用一个&前缀,spring容器就会知道要拿FactoryBean(工程bean)的本身。

提示:一定要分清FactoryBean和BeanFactory的区别,别混了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值