0%

factorybean和beanfactory

BeanFactory

​ BeanFactory是spring容器的顶级接口,或者就是源码说的root,根接口。

1
2
3
4
5
6
/**
* The root interface for accessing a Spring bean container.
*/
public interface BeanFactory {

}

​ BeanFactory不能够被实例化,而是定义了一套所有IOC容器必须遵守的规范。可以看看BeanFactory的结构,如下

结构

​ 多个重载方法,getBean(),从spring容器中获取bean对象。 containsBean()判断spring容器中是否包含某个bean。 还有判断bean的作用域,即是否为单例bean或者多例bean的方法,isSingleton和isPrototype,还有根据bean的名字获取名字等等…

具体的容器可以对其进行功能的增加,像spring中用到比较多的ApplicationContext,就是BeanFactory的子类。而ApplicationContext接口又衍生了很多的子类,像比较熟悉的ClassPathXmlApplicationContext、 AnnoationConfigApplicationContext。

类继承图


FactoryBean

​ FactoryBean也是一个接口,可以看官方注释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Interface to be implemented by objects used within a {@link BeanFactory} which
* are themselves factories for individual objects.
* ↑ 使用BeanFactory内的对象实现的接口,这些对象本身就是它们自己的工厂。。to be honest。。我也不是很明白这句话是什么意思。。。。
* If a bean implements this interface, it is used as a factory for an object to expose, not directly as a bean instance that will be exposed itself.
* 如果一个bean实现了这个接口,它可以作为暴露对象的工厂,而不是作为直接将自己暴露的bean实例。
*
* <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b> 实现这个接口的bean不能作为普通bean来使用
* A FactoryBean is defined in a bean style, but the object exposed for bean
* references ({@link #getObject()}) is always the object that it creates.
一个FactoryBean以bean的方式来定义,但是bean引用的对象一直都是它创建的对象。
*/
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;

@Nullable
Class<?> getObjectType();

default boolean isSingleton() {
return true;
}
}

​ 第一句话我自己不是很明白,可能他的意思是BeanFactory提供了spring容器的规范,实现了BeanFactory的类或接口中所使用的对象或实例,这些对象都可以作为单一对象的工厂。可能是想说明一个bean可以作为一个生产bean对象的工厂?

​ 接下来就清晰了一点,如果一个bean实现了FactoryBean这个接口,则它可以作为工厂来暴露对象,而不是把自己作为一个bean实例暴露,好像也很好的解释了前一句话,实现这个接口的bean可以作为工厂bean来生产bean。。。

最关键的就是最后一句,如果一个bean实现了FactoryBean,则说明它是一个工厂bean,但是,此时我们getBean() 来获取这个bean时,我们得到的不是它本身,而是它创建出来的对象,他创建出来的对象是什么? 正如它的注释里面的—– getObject()。


​ 举个例子,我们编写一个User类,并将其注入spring容器中。

1
2
3
4
5
6
7
8
9
10
11
12
@Data
public class User {
int age;
String name;

public User() {}

public User(int age, String name) {
this.age = age;
this.name = name;
}
}
1
2
3
4
<bean id="myUser" class="User" >
<property name="name" value="jack" />
<property name="age" value="12" />
</bean>

​ 在写一个类实现FactoryBean接口,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.beans.factory.FactoryBean;

public class UserBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new User();
}

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

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

​ 同样,注入spring容器

1
<bean id="userBean" class="UserBean"> </bean>

​ 可以来测试一下,通过getBean的方式来从spring容器中获取bean,结果userBean得到的结果是User类。

1
2
3
4
5
6
@Test
public void test05() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
Object userBean = context.getBean("userBean");
System.out.println(userBean.getClass().getName());
}

输出结果:

1
User

这是因为UserBean实现了FactoryBean接口,那么他就是一个工厂bean,它生产的bean是根据方法GetObject() 确定的,如果想要得到改对象,在bean的名字前面加上“&”即可。

1
Object userBean = context.getBean("&userBean");

总结

​ BeanFactory是spring的bean工厂,它是负责生产和管理bean的工厂,给spring容器提供了一系列的规范,所有的容器都必须遵守这一规范。

​ FactoryBean是在spring容器的基础上,给bean的实现加上一个简单的工厂模式,即生产bean的方式更加灵活了,我们可以在getObject() 方法中指定需要生产bean的类型。

-------------本文结束感谢您的阅读-------------