Spring中BeanFactory与FactoryBean的区别

在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混。

一、BeanFactory

BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean()containsBean()等管理Bean的通用方法。Spring的容器都是它的具体实现如:

  • DefaultListableBeanFactory
  • XmlBeanFactory
  • ApplicationContext

这些实现类又从不同的维度分别有不同的扩展。

1.1 BenaFactory源码

public interface BeanFactory {

    /**
     * 用来获得实例的引用,并且区分FactoryBean区分。
     * 如果使用bean的名字myJndiObject获取FactoryBean,返回的是一个工厂,而不是工厂的实例;如果需要获得工厂实例,需要转义。     */
    String FACTORY_BEAN_PREFIX = "&";

    /**
     * 根据bean的名称,获取指定的bean实例,该实例可以是共享的,也可以是独立的.     */
    Object getBean(String name) throws BeansException;

    /**
     * 根据bean的名称,获取指定的bean实例,该实例可以是共享的,也可以是独立的.并且增加了一个类型的检验。     */
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    /**
     * 根据给定类型返回匹配的bean实例.     */
    <T> T getBean(Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    /**
     * 检查spring的bean容器中是否包含有该bean     */
    boolean containsBean(String name);

    /**
     * 判断bean的作用域是否是singleton     */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    /**
     * 判断bena的作用域是否是prototype     */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    /**
     * 检查给定名称的bean是否和指定类型匹配.更确却的说是通过检查给定的bean,返回指定类型的目标对象     */
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 获取给定名称的bean的class类型     */
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    /**
     * 获取给定bean名称的别名,如果根据别名检索,将会获得原始bean名称。
     *
    String[] getAliases(String name);

}

1.2 使用场景

  • 从Ioc容器中获取Bean(byName or byType):context.getBean("father", Father.class)、context.getBean("father")
  • 检索Ioc容器中是否包含指定的Bean:  context.containsBean("father")
  • 判断Bean是否为单例:  context.isSingleton("father")

二、FactoryBean

首先它是一个Bean,但又不仅仅是一个Bean。它是一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何Bean的实例。

2.1 FactoryBean源码

public interface FactoryBean<T> {

    /**
     * 从工厂中获取bean实例
     */
    T getObject() throws Exception;

    /**
     * 从工厂中获取bean实例对象的类型
     */
    Class<?> getObjectType();

    /**
     * 工厂创建的对象是否是单例
     */
    boolean isSingleton();

}

从它定义的接口可以看出,FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上‘&‘符号。

  • getObject(‘name‘)返回工厂中的实例
  • getObject(‘&name‘)返回工厂本身的实例

通常情况下,bean 无须自己实现工厂模式,Spring 容器担任了工厂的 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。

2.2 示例

先定义一个Bean实现FactoryBean接口:

@Component
public class MyBean implements FactoryBean {
    private String message;
    public MyBean() {
        this.message = "通过构造方法初始化实例";
    }

    public MyBean(String message) {
        this.message = message;
    }

    @Override
    public Object getObject() throws Exception {
        // 这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例
        return new MyBean("通过FactoryBean.getObject()创建实例");
    }
    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }
    public String getMessage() {
        return message;
    }

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

MyBean实现了FactoryBean接口的三个方法,getObject()是可以返回任何对象的实例的,这里测试就返回MyBean自身实例,且返回前给message字段赋值。同时在构造方法中也为message赋值。然后测试代码中先通过名称获取Bean实例,打印message的内容,再通过&+名称获取实例并打印message内容。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = HelloApplication.class)
public class FactoryBeanTest {
    @Autowired
    private ApplicationContext context;
    @Test
    public void test() {
        MyBean myBean1 = (MyBean) context.getBean("myBean");//返回工厂中的实例,调用FactoryBean.getObject()创建实例
        System.out.println("myBean1 = " + myBean1.getMessage());
        MyBean myBean2 = (MyBean) context.getBean("&myBean");//返回工厂本身,通过构造方法初始化实例
        System.out.println("myBean2 = " + myBean2.getMessage());
        System.out.println("myBean1.equals(myBean2) = " + myBean1.equals(myBean2));
    }
}

打印结果:

myBean1 = 通过FactoryBean.getObject()创建实例
myBean2 = 通过构造方法初始化实例
myBean1.equals(myBean2) = false

2.3 使用场景

说了这么多,为什么要有FactoryBean这个东西呢,有什么具体的作用吗?
FactoryBean在Spring中最为典型的一个应用就是用来创建AOP的代理对象。

我们知道AOP实际上是Spring在运行时创建了一个代理对象,也就是说这个对象,是我们在运行时创建的,而不是一开始就定义好的,这很符合工厂方法模式。更形象地说,AOP代理对象通过Java的反射机制,在运行时创建了一个代理对象,在代理对象的目标方法中根据业务要求织入了相应的方法。这个对象在Spring中就是——ProxyFactoryBean

所以,FactoryBean为我们实例化Bean提供了一个更为灵活的方式,我们可以通过FactoryBean创建出更为复杂的Bean实例。

三、区别

  • 他们两个都是个工厂,但FactoryBean本质上还是一个Bean,也归BeanFactory管理
  • BeanFactory是Spring容器的顶层接口,FactoryBean更类似于用户自定义的工厂接口。

原文地址:https://www.cnblogs.com/heqiyoujing/p/12077573.html

时间: 2024-11-09 00:47:30

Spring中BeanFactory与FactoryBean的区别的相关文章

Spring中BeanFactory和ApplicationContext的区别

我用一个例子去测试BeanFactory和ApplicationContext的区别 首先建立一个bean public class User {//声明无参构造,打印一句话,监测对象创建时机 public User(){ System.out.println("User对象初始化"); } } 然后再建立测试类 public class UserTest { @Test public void ApplicationContexttest(){ ApplicationContext

Spring中ClassPathXmlApplication与FileSystemXmlApplicationContext的区别

Spring中ClassPathXmlApplication与FileSystemXmlApplicationContext的区别 一.概述 在项目中遇到加载不到Spring配置文件,简单分析后,写此文备忘! 二.测试所需资源 TestBean.java public class TestBean { public TestBean(){ System.out.println(this.getClass().getName().concat(" init !")); } public

【转载】Spring中DispatcherServlet与ContextLoaderListener的区别

昨天在写springmvc的时候,在web.xml中配置了DispatcherServlet,如下: <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>

Spring中Adivisor和Aspect的区别(自我理解)

在AOP中有几个概念: - 方/切 面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象.事务管理是J2EE应用中一个很好的横切关注点例子.方面用Spring的Advisor或拦截器实现. - 连接点/织入点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出. - 通知(Advice):在特定的连接点,AOP框架执行的动作.各种类型的通知包括"around"."before"和"throws"通知

Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法

1. BeanFactory BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于管理Bean的一个工厂.在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化.定位.配置应用程序中的对象及建立这些对象间的依赖. Spring为我们提供了许多易用的BeanFactory实现,XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系.XmlBeanFactory类将持有此XML配置元数据,并用它来构

Spring之BeanFactory和FactoryBean接口的区别

目录 一.BeanFactory接口 二.FactoryBean接口 1.简单实现 2.增强实现 3.FactoryBean的实际使用案例 三.总结 @ ??Spring框架中的BeanFactory接口和FactoryBean接口因为名称相似,老是容易搞混淆,而且也是面试过程中经常会碰到的一个问题.所以本文就专门给大家整理出来. 一.BeanFactory接口 ??BeanFactory接口是Spring容器的核心接口,负责:实例化.定位.配置应用程序中的对象及建立这些对象间的依赖. ??Sp

Spring中的BeanFactory和FactoryBean的区别

一句话介绍 BeanFactory接口用来生产Bean,它处理生产bean的接口体系的最顶层,getBean方法可以获取bean.FactoryBean接口用来定制Bean的生产过程,getObject方法中可以实现自定义过程. 源码 BeanFactory源码 public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String var1) throws BeansExce

BeanFactory与FactoryBean的区别

有很多常用的FactoryBean类: 1.org.springframework.scheduling.quartz.SchedulerFactoryBean 2.org.springframework.scheduling.quartz.CronTriggerFactoryBean 3.org.springframework.scheduling.quartz.SimpleTriggerFactoryBean 4.org.springframework.scheduling.quartz.J

Spring中@Component和@Bean的区别

Spring 管理Bean的方式 Spring管理Bean分为两个部分,一个是注册Bean,一个装配Bean. 完成这两个动作有三种方式,一种是使用自动配置的方式.一种是使用JavaConfig的方式,一种就是使用XML配置的方式. @Component 把普通pojo实例化到spring容器中 @Bean 需要在配置类中使用,即类上需要加上@Configuration注解 两者都能通过@Autowired注解自动装配 @Compent和@Bean到底区别在哪? 在应用开发的过程中,如果想要将第