Spring之BeanFactory与FactoryBean的区别

BeanFactory

BeanFactory是Spring中工厂的顶层接口,也是IOC容器的核心接口,BeanFactory中定义了管理Bean的通用方法,职责包括实例化、定位、配置应用程序中的对象以及建立这些对象的依赖。BeanFactory只是一个接口,并不是IOC容器的具体实现。

常用方法如下:

  • 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所对应的所有的别名

主要的实现类:

  • DefaultListableBeanFactory:Spring默认的工厂类
  • XmlBeanFactory:前期使用XML配置用的比较多的时候用的Bean工厂
  • ClassPathXmlApplicationContext:XML解析上下文对象,用户创建Bean对象我们早期写Spring的时候用的就是他

 BeanFactory部分源码

public interface BeanFactory {
	//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
	//如果需要得到工厂本身,需要转义
	String FACTORY_BEAN_PREFIX = "&";
	//根据bean的名字,获取在IOC容器中得到bean实例
	Object getBean(String name) throws BeansException;
	//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。
	<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;

    .......

	//提供对bean的检索,看看是否在IOC容器有这个名字的bean
	boolean containsBean(String name);
	//根据bean名字得到bean实例,并同时判断这个bean是不是单例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    .......

	//得到bean实例的Class类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
	String[] getAliases(String name);
}

BeanFactory的使用场景

  • 从IOC容器中获取Bean对象(byName 或 byType)
  • 检索IOC容器中是否包含指定的Bean对象
  • 判断Bean对象是否为单例

FactoryBean

FactoryBean也是一个Bean,但该Bean是一个能生成或修饰对象生成的工厂Bean,他的实现与设计模式中的工厂模式和修饰器模式类似,用户可以通过实现该接口来自定义该Bean接口的实例化过程。这里可能会有疑惑为什么不能在XML文件中配置Bean,而要使用FactoryBean去创建Bean,这里可以分两点:

  1. 在某些情况下实例化Bean过程比较复杂,如果使用传统的方式,则需要提供大量的配置信息,配置方式的灵活性受限,如果采用编码的方式可能会得到一个简单的方案。
  2. 第三方库不能直接注册到Spring容器当中,于是可以实现FactoryBean接口,然后给出自己对象的实例化代码即可。

常用方法如下:

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

接下来简单展示一下代码示例

在XML文件中配置两个Bean

<?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="person" class="com.zmt.factoryBeanDemo.entity.Person">
        <property name="age" value="10"/>
        <property name="name" value="小明"/>
    </bean>

    <bean id="personFromFactoryBean" class="com.zmt.factoryBeanDemo.factoryBean.PersonFactoryBean">
        <property name="init" value="10,小红"/>
    </bean>

</beans>

两种Bean的具体代码

public class Person {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class PersonFactoryBean implements FactoryBean<Person> {
    private String init;

    public void setInit(String init) {
        this.init = init;
    }

    @Override
    public Person getObject() throws Exception {
        //处理初始化内容
        String[] split = init.split(",");
        Person person = new Person();
        String strAge = split[0];
        String name = split[1];
        person.setAge(Integer.parseInt(strAge));
        person.setName(name);
        return person;
    }

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

main方法测试

public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        //通过xml配置创建的Bean
        Person person = context.getBean("person", Person.class);
        System.out.println(person.getName());
        //通过FactoryBean创建的Bean
        Person personByFactoryBean = context.getBean("personFromFactoryBean", Person.class);
        System.out.println(personByFactoryBean.getName());
    }
}

运行结果如下

小明
小红

FactoryBean的使用场景

在Spring中最经典的一个应用就是用来创建AOP的代理对象。AOP实际上就是Spring在运行时创建一个代理对象,而不是一开始就定义好的,或者说AOP代理对象通过Java的反射机制在运行时创建了一个代理对象,在代理对象的目标方法中根据业务需求织入了相应的方法,在个对象在Spring中就是ProxyFactoryBean

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zmbwcx2003

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值