当前位置: 代码迷 >> 综合 >> BeanFactory 和 FactoryBean
  详细解决方案

BeanFactory 和 FactoryBean

热度:30   发布时间:2024-01-09 11:21:05.0

1.前言

BeanFactory 和 FactoryBean可以说是毫不相干的两个东西,但又有千丝万缕的关系。从字面上看,bean工厂 和 工厂bean,一句话描述它们之间的区别的关系:BeanFactory 是用来管理所有bean的工厂类,FactoryBean是一个bean,生产某种类的bean,它本身也是一个bean。

2.深入了解

我们所知道的bean的创建方式有哪几种呢?

  • 使用Spring XML方式配置,该方式用于在纯Spring 应用中,适用于简单的小应用,当应用变得复杂,将会导致XMl配置文件膨胀 ,不利于对象管理。
<bean id="xxxx" class="xxxx.xxxx"/>
  • 使用@Component,@Service,@Controler,@Repository注解
  • 使用@Bean注解
  • 使用注解@Import,也会创建对象并注入容器中
  • 使用ImportSelector或者ImportBeanDefinitionRegistrar接口,配合@Import实现
  • 手动注入Bean容器,有些场景下需要代码动态注入,以上方式都不适用。

而在XML方式种,有分几种类,通过构造方法,setter方法,还有通过工厂类的方式来创建bean。而工厂类的方式就和我们这篇文章所说FactoryBean有关系。

我们把bean分为两种,一种为普通bean,一种为工厂bean。之所以这样分类,你可以理解为,普通bean的创建方式比较简单,可以在XML中配置,但是工厂bean比较复杂,需要用到很多初始化参数等等,此时放在XML中配置就显得很复杂,于是我们可以通过工厂bean,来创建这个复杂的对象。

说到这里,我相信你已经明白两个的区别了。

3.继续深入了解

3.1 BeanFactory

这个其实是所有Spring Bean的容器根接口,给Spring 的容器定义一套规范,给IOC容器提供了一套完整的规范,比如我们常用到的getBean方法等

定义方法:

  • getBean(String name): Spring容器中获取对应Bean对象的方法,如存在,则返回该对象
  • containsBean(String name):Spring容器中是否存在该对象
  • isSingleton(String name):通过beanName是否为单例对象
  • isPrototype(String name):判断bean对象是否为多例对象
  • isTypeMatch(String name, ResolvableType typeToMatch):判断name值获取出来的bean与typeToMath是否匹配
  • getType(String name):获取Bean的Class类型
  • getAliases(String name):获取name所对应的所有的别名

主要的实现类(包括抽象类):

  • AbstractBeanFactory:抽象Bean工厂,绝大部分的实现类,都是继承于他
  • DefaultListableBeanFactory:Spring默认的工厂类
  • XmlBeanFactory:前期使用XML配置用的比较多的时候用的Bean工厂
  • AbstractXmlApplicationContext:抽象应用容器上下文对象
  • ClassPathXmlApplicationContext:XML解析上下文对象,用户创建Bean对象我们早期写Spring的时候用的就是他

使用方式:

  1. 使用ClassPathXmlApplicationContext读取对应的xml文件实例对应上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
    "applicationContext.xml"});
BeanFactory factory = (BeanFactory) context;

3.2 FactoryBean

该类是SpringIOC容器是创建Bean的一种形式,这种方式创建Bean会有加成方式,融合了简单的工厂设计模式于装饰器模式.
有些人就要问了,我直接使用Spring默认方式创建Bean不香么,为啥还要用FactoryBean做啥,在某些情况下,对于实例Bean对象比较复杂的情况下,使用传统方式创建bean会比较复杂,例如(使用xml配置),这样就出现了FactoryBean接口,可以让用户通过实现该接口来自定义该Bean接口的实例化过程。即包装一层,将复杂的初始化过程包装,让调用者无需关系具体实现细节。

方法:

  • T getObject():返回实例
  • Class<?> getObjectType();:返回该装饰对象的Bean的类型
  • default boolean isSingleton():Bean是否为单例

常用类:

  • ProxyFactoryBean :Aop代理Bean
  • GsonFactoryBean:Gson

使用:

  1. Spring XML方式

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="demo" class="cn.lonecloud.spring.example.bo.Person"><property name="age" value="10"/><property name="name" value="xiaoMing"/></bean><bean id="demoFromFactory" class="cn.lonecloud.spring.example.bean.PersonFactoryBean"><property name="initStr" value="10,init from factory"/></bean>
</beans>

personFactoryBean.java

public class PersonFactoryBean implements FactoryBean<Person> {
    /*** 初始化Str*/private String initStr;@Overridepublic Person getObject() throws Exception {
    //这里我需要获取对应参数Objects.requireNonNull(initStr);String[] split = initStr.split(",");Person p=new Person();p.setAge(Integer.parseInt(split[0]));p.setName(split[1]);//这里可能需要还要有其他复杂事情需要处理return p;}@Overridepublic Class<?> getObjectType() {
    return Person.class;}public String getInitStr() {
    return initStr;}public void setInitStr(String initStr) {
    this.initStr = initStr;}
}

main方法

public class SpringBeanFactoryMain {
    public static void main(String[] args) {
    //这个是BeanFactoryBeanFactory beanFactory = new ClassPathXmlApplicationContext("application.xml");//获取对应的对象化Object demo = beanFactory.getBean("demo");System.out.println(demo instanceof Person);System.out.println(demo);//获取从工厂Bean中获取对象Person demoFromFactory = beanFactory.getBean("demoFromFactory", Person.class);System.out.println(demoFromFactory);//获取对应的personFactoryObject bean = beanFactory.getBean("&demoFromFactory");System.out.println(bean instanceof PersonFactoryBean);PersonFactoryBean factoryBean=(PersonFactoryBean) bean;System.out.println("初始化参数为:"+factoryBean.getInitStr());}
}

输出

true
Person{name=‘xiaoMing’, age=10}
Person{name=‘init from factory’, age=10}
true
初始化参数为:10,init from factory

区别

  1. BeanFactory:负责生产和管理Bean的一个工厂接口,提供一个Spring Ioc容器规范,
  2. FactoryBean: 一种Bean创建的一种方式,对Bean的一种扩展。对于复杂的Bean对象初始化创建使用其可封装对象的创建细节。
  相关解决方案