Spring组件注册-BeanFactory使用

一起学习,共同进步~

文章内容

我们在之前使用过@ComponentScan结合@Controller、@Service、@Component、@Repository往Spring容器中注册组件,也使用过实现ImportSelector和ImportBeanDefinitionRegistrar接口结合@Import往Spring容器中注册组件。我们再来看一种使用FactoryBean往容器中注册组件。


FactoryBean了解


先来看一下FactoryBean接口,我在下面的方法上加上注释

<code>public interface FactoryBean {

    /**
     * 返回一个由该工厂管理的的Bean实例
     */
    @Nullable
    T getObject() throws Exception;

    /**
     * 返回由该工厂管理的Bean的类型
     */
    @Nullable
    Class> getObjectType();

    /**
     * 返回该工厂管理的对象是否是单例
     * 这是一个default方法,默认返回true
     */
    default boolean isSingleton() {
        return true;
    }
}
/<code>

我们来实现以下这个接口试着注册一个Bean。


FactoryBean使用


  • 我们来创建一个Grapes类,后面就将这个类注册到Spring容器中
<code>package cn.nesive.spring.factorybean;

public class Grapes {}/<code>
  • 接着我们实现FactoryBean接口,将Grapes类注册到Spring容器中
<code>package cn.nesive.spring.factorybean;

import org.springframework.beans.factory.FactoryBean;

public class GrapesFactoryBean implements FactoryBean<grapes> {


    @Override
    public Grapes getObject() throws Exception {
        return new Grapes();
    }

    @Override
    public Class> getObjectType() {
        return Grapes.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}/<grapes>/<code>
  • 创建一个配置类,并通过@Import注解将GrapesFactoryBean交由Spring管理
<code>package cn.nesive.spring.factorybean; 


import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(value = {GrapesFactoryBean.class})
public class FactoryBeanConfig {}/<code>
  • 看看此刻Spring容器中所包含的Bean实例都有那些,我们打印一下容器中所有的Bean定义信息
<code>package cn.nesive.spring.factorybean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class FactoryBeanTest {
    @Test
    public void test01(){
        ApplicationContext context = new AnnotationConfigApplicationContext(
                FactoryBeanConfig.class
        );
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}/<code>

运行结果:

<code>org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
factoryBeanConfig
cn.nesive.spring.factorybean.GrapesFactoryBean/<code>

我们发现此这里并没有我们想要的Grapes对象,那是怎么回事呢? 原因就是cn.nesive.spring.factorybean.GrapesFactoryBean这个名称实际上定义的就是Grapes对象。 那我们来瞅瞅~


Bean和BeanFactoryBean


<code>package cn.nesive.spring.factorybean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class FactoryBeanTest {
    @Test
    public void test01() throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(
                FactoryBeanConfig.class
        );
        Grapes factoryBean = (Grapes)context.getBean(
                "cn.nesive.spring.factorybean.GrapesFactoryBean"
        );
        // 查询cn.nesive.spring.factorybean.GrapesFactoryBean的实例类型
        System.out.println(factoryBean.getClass());
        // 查看是否单例
        System.out.println(factoryBean == context.getBean(Grapes.class));
    }
}/<code>

运行结果:

<code>class cn.nesive.spring.factorybean.Grapes
true/<code>

那么可以我们定义名称为cn.nesive.spring.factorybean.GrapesFactoryBean的Bean实例实际上是cn.nesive.spring.factorybean.Grapes类型。并且它是单例的。

由于我们在配置类中使用Import导入的组件是GrapesFactoryBean。那么我们想要获取GrapesFactoryBean实例怎么办呢? 答案就是需要在cn.nesive.spring.factorybean.GrapesFactoryBean之前加上"&"符号。我们来看看BeanFatory接口的FACTORY_BEAN_PREFIX注释信息俩看看,大概意思就是:

<code>用于取消对FactoryBean实例的引用,并将其与FactoryBean创建的bean区分开来。例如,如果名为myJndiObject的bean是FactoryBean,那么获取&myJndiObject将返回工厂,而不是工厂返回的实例。/<code> 

那我们尝试一下在Spring容器中获取工厂实例。


获取FactoryBean实例

<code>package cn.nesive.spring.factorybean;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class FactoryBeanTest {
    @Test
    public void test01() throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(
                FactoryBeanConfig.class
        );
        // 加上前缀"&",获取工厂实例
        GrapesFactoryBean factoryBean = (GrapesFactoryBean)context.getBean(
                "&cn.nesive.spring.factorybean.GrapesFactoryBean"
        );
        System.out.println(factoryBean.getClass());
    }
}/<code>

来看看运行结果:

<code>class cn.nesive.spring.factorybean.GrapesFactoryBean/<code>

可以看到加上前缀"&"这个时候就返回了工厂实例。



分享到:


相關文章: