您现在的位置是:亿华云 > IT科技
面试官:BeanFactory和FactoryBean有哪些区别?
亿华云2025-10-08 20:53:03【IT科技】3人已围观
简介区别说实话,他俩除了名字比较像以外,好像没有其他共同点了。「BeanFactory和FactoryBean有哪些区别?」BeanFactory是一个最基础的IOC容器,提供了依赖查找,依赖注入等基础的
区别
说实话,面试他俩除了名字比较像以外,有区好像没有其他共同点了。面试
「BeanFactory和FactoryBean有哪些区别?有区」
BeanFactory是一个最基础的IOC容器,提供了依赖查找,面试依赖注入等基础的有区功能 FactoryBean是创建Bean的一种方式,帮助实现复杂Bean的面试创建和BeanFactory相关的还有一个高频的面试题
「ApplicationContext和BeanFactory有哪些区别?」
BeanFactory是一个最基础的IOC容器,提供了依赖查找,有区依赖注入等基础的面试功能 ApplicationContext继承了BeanFactory,在BeanFactory的有区基础上增加了企业级的功能,如AOP,面试资源管理(Resources)事件(Event),有区国际化(i18n),面试Environment抽象等创建Bean的有区方式
常见的创建Bean的方式有如下四种
通过构造器 通过静态工厂方法 通过Bean工厂方法 通过FactoryBean @Data @ToString public class User { private Long id; private String name; public static User createUser() { User user = new User(); user.setId(1L); user.setName("li"); return user; } } public class UserFactory { public User createUser() { return User.createUser(); } } public class UserFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { return User.createUser(); } @Override public Class<?> getObjectType() { return User.class; } } <?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 构造方法实例化 Bean --> <bean id="user-by-constructor" class="com.javashitang.domain.User"> <property name="id" value="1"/> <property name="name" value="li"/> </bean> <!-- 静态方法实例化 Bean --> <bean id="user-by-static-method" class="com.javashitang.domain.User" factory-method="createUser"/> <bean id="userFactory" class="com.javashitang.factory.UserFactory"/> <!-- Bean工厂方法实例化 Bean --> <bean id="user-by-factory" factory-bean="userFactory" factory-method="createUser"/> <!-- FactoryBean实例化 Bean --> <bean id="user-by-factory-bean" class="com.javashitang.factory.UserFactoryBean"/> </beans> public class BeanInstantiationDemo { public static void main(String[] args) { BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/bean-instantiation-context.xml"); User user1 = beanFactory.getBean("user-by-constructor", User.class); User user2 = beanFactory.getBean("user-by-static-method", User.class); User user3 = beanFactory.getBean("user-by-factory", User.class); User user4 = beanFactory.getBean("user-by-factory-bean", User.class); } }实现原理
在分析源码之前,我们先明确2个概念
「factoryBean是面试我们配置到容器中的云服务器实现FactoryBean接口的Bean,而subBean是用FactoryBean创建出来的Bean」
在Spring容器启动的过程中,会实例化非延迟的单例Bean,即调用如下方法 DefaultListableBeanFactory#preInstantiateSingletons
调用FactoryBean#getObject的链路如下图
通过分析DefaultListableBeanFactory#preInstantiateSingletons方法和FactoryBean#getObject的调用链路可以分析得到
单例的factoryBean对象本身会在spring容器启动时主动初始化。而subBean的初始化则是在第一次从缓存中获取factoryBean并且不为空才会触发 如果factoryBean对象实现的接口是SmartFactoryBean且isEagerInit方法返回true,那么subBean对象也会在spring容器启动的时候主动初始化 如果bean注册的时候,beanName对应的bean实例是一个factoryBean,那么我们通过getBean(beanName)获取到的对象将会是subBean对象;如果要获取工厂对象factoryBean,需要使用getBean("&" + beanName) 单例的subBean也会缓存在spring容器中,具体的容器是FactoryBeanRegistrySupport#factoryBeanObjectCache,香港云服务器一个Map「建议大家看一下DefaultListableBeanFactory#preInstantiateSingletons方法和FactoryBean#getObject方法的调用链路,就能理解上面我说的流程了,我就不贴太多源码了」
应用
目前我只在Dubbbo源码中看到了FactoryBean的应用
「服务导出:在Dubbo中,服务提供者会被包装成ServiceBean对象,当监听到ContextRefreshedEvent事件时开始服务导出」
「服务调用:服务调用方会被包装成ReferenceBean对象,ReferenceBean实现了FactoryBean接口和InitializingBean接口,创建subBean的逻辑在ReferenceBean#getObject方法中」
「Dubbo服务引入的时机有如下2种。」
饿汉式:init=true,在Bean生命周期的初始化阶段会调用InitializingBean#afterPropertiesSet方法,而这个方法会调用ReferenceBean#getObject方法,完成subBean的创建,即ReferenceBean实例化时完成服务引入 懒汉式:init=false,在ReferenceBean对应的服务被注入到其他类中时,此时会调用AbstractApplicationContext#getBean,获取ReferenceBean对象,因为ReferenceBean实现了FactoryBean接口,所以会调用ReferenceBean#getObject方法,完成subBean的创建,即完成服务引入 public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean { @Override public Object getObject() { return get(); } @Override @SuppressWarnings({ "unchecked"}) public void afterPropertiesSet() throws Exception { // 省略部分代码 if (shouldInit()) { getObject(); } } }本文转载自微信公众号「Java识堂」,可以通过以下二维码关注。转载本文请联系Java识堂公众号。
很赞哦!(89221)
相关文章
- 公司名字不但要与其经营理念、活动识别相统一,还要能反映公司理念,服务宗旨、商品形象,从而才能使人看到或听到公司的名称就能产生愉快的联想,对商店产生好感。这样有助于公司树立良好的形象。
- 写给技术人员:停止学习框架,要专注基础知识
- Vim哭了,浏览器就能远程VS Code开发,还支持Docker快速部署运行
- 蚂蚁金服开源 SOFAJRaft:生产级 Java Raft 算法库
- 国内域名
- 如何通俗易懂的向面试官解释什么是 RPC 框架
- “流浪地球”计划最终成功,里面这位程序员功不可没!
- 996、小白兔、中年危机,互联网累了也老了
- 什么是im域名?新手需要了解im域名哪些?
- 网友编写出《流浪地球》“春节十二响”C语言源码