第四十三讲 FactoryBean
第四十三讲 FactoryBean
从这一讲开始,我们来讲一些相对比较零散的知识, 这些知识是对之前知识的查漏补缺。
本讲我们来讲一下FactoryBean的工作机制和缺憾。
这个FactoryBean是一个工厂Bean, 它是用来产生一个产品对象的。这个FactoryBean本身是受Spring容器管理的,但是FactoryBean产生出来的Bean,只能说是一部分受到Spring容器的管理,为什么这么说呢,我们下面做一个实验来演示一下。
@ComponentScan
public class A43 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A43.class);
Bean1 bean1 = (Bean1) context.getBean("bean1");
Bean1 bean2 = (Bean1) context.getBean("bean1");
Bean1 bean3 = (Bean1) context.getBean("bean1");
System.out.println(bean1);
System.out.println(bean2);
System.out.println(bean3);
System.out.println(context.getBean(Bean1.class));
System.out.println(context.getBean(Bean1FactoryBean.class));
System.out.println(context.getBean("&bean1"));
context.close();
/*
学到了什么: 一个在 Spring 发展阶段中重要, 但目前已经很鸡肋的接口 FactoryBean 的使用要点
说它鸡肋有两点:
1. 它的作用是用制造创建过程较为复杂的产品, 如 SqlSessionFactory, 但 @Bean 已具备等价功能
2. 使用上较为古怪, 一不留神就会用错
a. 被 FactoryBean 创建的产品
- 会认为创建、依赖注入、Aware 接口回调、前初始化这些都是 FactoryBean 的职责, 这些流程都不会走
- 唯有后初始化的流程会走, 也就是产品可以被代理增强
- 单例的产品不会存储于 BeanFactory 的 singletonObjects 成员中, 而是另一个 factoryBeanObjectCache 成员中
b. 按名字去获取时, 拿到的是产品对象, 名字前面加 & 获取的是工厂对象
就说恶心不?
但目前此接口的实现仍被大量使用, 想被全面废弃很难
*/
}
}
public class Bean1 implements BeanFactoryAware {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
private Bean2 bean2;
@Autowired
public void setBean2(Bean2 bean2) {
log.debug("setBean2({})", bean2);
this.bean2 = bean2;
}
public Bean2 getBean2() {
return bean2;
}
@PostConstruct
public void init() {
log.debug("init");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
log.debug("setBeanFactory({})", beanFactory);
}
}
@Component("bean1")
public class Bean1FactoryBean implements FactoryBean<Bean1> {
private static final Logger log = LoggerFactory.getLogger(Bean1FactoryBean.class);
// 决定了根据【类型】获取或依赖注入能否成功
@Override
public Class<?> getObjectType() {
return Bean1.class;
}
// 决定了 getObject() 方法被调用一次还是多次
@Override
public boolean isSingleton() {
return true;
}
@Override
public Bean1 getObject() throws Exception {
Bean1 bean1 = new Bean1();
log.debug("create bean: {}", bean1);
return bean1;
}
}
@Component
public class Bean1PostProcessor implements BeanPostProcessor {
private static final Logger log = LoggerFactory.getLogger(Bean1PostProcessor.class);
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean1") && bean instanceof Bean1) {
log.debug("before [{}] init", beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean1") && bean instanceof Bean1) {
log.debug("after [{}] init", beanName);
}
return bean;
}
}
@Component
public class Bean2 { }
分类:
Spring 高级49讲
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构