BeanFactory和FactoryBean

先说结论:

BeanFactory: 是 IOC 容器,并且提供方法支持外部程序对这些 bean 的访问,在程序启动时 根据传入的参数产生各种类型的 bean,并添加到 IOC容器(实现 BeanFactory 接口的类) 的 singletonObject 属性中。

FactoryBean: 首先是个 bean,也存放在 BeanFactory 中。它具有工厂方法的功能,在程序运行中 产生指定(一种)类型的 bean,并添加到了 IOC容器中的 factoryBeanObjectCache 属性中。

BeanFactory是Spring提供的存放Bean的工厂,FactoryBean是一个可生产Bean的工厂Bean

FactoryBean和BeanFactory都是spring的一个类工厂,BeanFactory只能生产一种类型的类,FactoryBean可以生产两种类型的类,一种跟BeanFactory类似,生产的是当前对象,另一种是通过getObject()返回的对象。

一、BeanFactory

先来说说BeanFactory,这个其实是所有Spring Bean的容器根接口。这是Spring bean容器的基本客户端视图。原来是获取Spring Bean的接口,也就是IoC容器。然后我们看类图
在这里插入图片描述

1、定义方法:

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

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

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

使用ClassPathXmlApplicationContext读取对应的xml文件实例对应上下文对象

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
BeanFactory factory = (BeanFactory) context;

4、BeanFactory的使用场景:

  • 通过 名字或类型从容器中获取 bean。
  • 判断容器中是否包含指定的 bean。
  • 判断 bean 是不是单例。

二、FactoryBean

1、FactoryBean的源码:

public interface FactoryBean<T> {
	
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
    
	//自定义创建bean方式
	@Nullable
	T getObject() throws Exception;

	// 从 beanFactory 中获取bean的类型。
	@Nullable
	Class<?> getObjectType();

	//默认单例
	default boolean isSingleton() {
		return true;
	}
    
}


2、如何使用FactoryBean

@Service
public class MyFactoryBean implements FactoryBean {


    @Override
    public Object getObject() throws Exception {
		//手动创建bean
        return new PersonServiceImpl();
    }

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

	//这个方法可以不用覆写,父类默认是单例,如果想设置成非单例可以覆写方法返回false
    public boolean isSingleton() {
        return false;
    }
}

创建PersonServiceImpl类,这里我们没有使用@Service注解,说明应用启动时不会放入IOS容器中

public class PersonServiceImpl implements PersonService{

    public void test() {
        System.out.println("3333333");
    }
}
@SpringBootTest
class DemoApplicationTests {

    @Autowired
    ApplicationContext applicationContext;

    @Test
    void test() {
        PersonService bean = applicationContext.getBean(PersonService.class);
        System.out.println(bean);
        bean.test();
        PersonService bean2 = applicationContext.getBean(PersonService.class);
        System.out.println(bean2);
    }

}

编写测试类通过applicationContext的getBean()方法从容器中获取PersonService的bean,发现可以获取到,说明获取bean时发现容器中存在FactoryBean 的实现类MyFactoryBean 并判断传入的类型是否是PersonService如果一样,则返回getObject()方法对象。 这里我们调用了两次bean是不一样的,说明我们设置成了非单例模式

3、FactoryBean的使用场景:
说了这么说,为什么需要 FactoryBean ,它的特殊功能是什么呢?

Spring 中 FactoryBean 最大的应用场景是用在 AOP 中。我们都知道,AOP 实际上是 Spring 在运行是创建出来的代理对象,这个对象是在运行时才被创建的,而不是在启动时定义的,这与工厂方法模式是一致的。更生动地说,AOP 代理对象通过 java 反射机制在运行时创建代理对象,并根据业务需求将相应的方法编织到代理对象的目标方法中。Spring 中的 ProxyFactoryBean 就是干这事的。

因此,FactoryBean 提供了更灵活的实例化 bean 的方法。通过 FactoryBean 我们可以创建更复杂的 bean。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值