The difference between BeanFactory and FactoryBean in Spring

In Spring, there are two interfaces, BeanFactory and FactoryBean, which are very similar in name and easy to confuse.

1. BeanFactory

BeanFactoryIt is an interface, which is the top-level specification of the factory in Spring and the core interface of the SpringIoc container. It defines the common methods of managing beans such as getBean(), containsBean()etc. Spring's container is its specific implementation such as:

  • DefaultListableBeanFactory

  • XmlBeanFactory

  • ApplicationContext

These implementation classes have different extensions from different dimensions.

1.1. Source code

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;

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

	<T> T getBean(Class<T> requiredType) throws BeansException;

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

	//提供对bean的检索,看看是否在IOC容器有这个名字的bean
	boolean containsBean(String name);

	//根据bean名字得到bean实例,并同时判断这个bean是不是单例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

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

	//得到bean实例的Class类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
	String[] getAliases(String name);
}

1.1. Usage scenarios

  • Get Bean(byName or byType) from Ioc container
  • Retrieves whether the specified bean is contained in the Ioc container
  • Determine whether a bean is a singleton

二、FactoryBean

First of all it is a bean, but not just a bean. It is a factory bean that can produce or decorate objects, similar to the factory pattern and decorator pattern in the design pattern. It can produce an object when needed, and it is not limited to itself, it can return an instance of any Bean.

2.1. Source code

public interface FactoryBean<T> {

	//从工厂中获取bean
	@Nullable
	T getObject() throws Exception;

	//获取Bean工厂创建的对象的类型
	@Nullable
	Class<?> getObjectType();

	//Bean工厂创建的对象是否是单例模式
	default boolean isSingleton() {
		return true;
	}
}

As can be seen from the interface it defines, it FactoryBeanrepresents the responsibility of a factory. That is, if a bean A implements the FactoryBean interface, then A becomes a factory. According to the name of A, getObject()the object returned by the factory call is actually obtained, not A itself. If you want to obtain an instance of factory A itself, then You need to prefix the name with a ' &' symbol.

  • getObject('name') returns the instance in the factory
  • getObject('&name') returns an instance of the factory itself

Usually, beans do not need to implement the factory pattern themselves, and the Spring container acts as a factory; but in a few cases, the beans in the container themselves are factories, and their role is to generate other bean instances. Other bean instances produced by the factory bean are no longer produced by the Spring container, so unlike normal bean configuration, the class element no longer needs to be provided.

2.2. Examples

First define a Bean to implement the FactoryBean interface

@Component
public class MyBean implements FactoryBean {
    private String message;
    public MyBean() {
        this.message = "通过构造方法初始化实例";
    }
    @Override
    public Object getObject() throws Exception {
        // 这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例。
        //如return new Student()...
        return new MyBean("通过FactoryBean.getObject()创建实例");
    }
    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }
    public String getMessage() {
        return message;
    }
}

MyBean implements two methods of the FactoryBean interface. getObject() can return an instance of any object. Here, the test returns the instance of MyBean itself, and assigns a value to the message field before returning. At the same time, the message is also assigned a value in the construction method. Then in the test code, first obtain the Bean instance by name, print the content of the message, and then &+名称obtain the instance and print the content of the message.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class FactoryBeanTest {
    @Autowired
    private ApplicationContext context;
    @Test
    public void test() {
        MyBean myBean1 = (MyBean) context.getBean("myBean");
        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. Usage scenarios

Having said so much, why is there FactoryBeansuch a thing, and does it have any specific effect?
One of the most typical applications of FactoryBean in Spring is to create proxy objects of AOP .

We know that AOP actually creates a proxy object at runtime by Spring, which means that this object is created by us at runtime, not defined at the beginning, which is in line with the factory method pattern. More vividly, the AOP proxy object creates a proxy object at runtime through the reflection mechanism of Java, and weaves the corresponding methods into the target method of the proxy object according to the business requirements. This object in Spring is -- ProxyFactoryBean.

Therefore, FactoryBean provides a more flexible way for us to instantiate beans, and we can create more complex Bean instances through FactoryBean.

3. Difference

  • Both of them are factories, but they are FactoryBeanstill a Bean in essence, and they are also BeanFactorymanaged
  • BeanFactoryIt is the top-level interface of the Spring container, FactoryBeanmore similar to the user-defined factory interface.
总结

BeanFactoryThe difference between and FactoryBeanis indeed easy to confuse, and rote memorization is not enough. It is best to understand it from the source code level and in the spring environment.

Reference:
https://www.cnblogs.com/yulinfeng/p/11456587.html
https://www.cnblogs.com/guitu18/p/11284894.html

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324119961&siteId=291194637