innosetup 同名文件替换_「面试」你是否清楚Spring中同名bean的解决方案?

分享自己在Java方面的所思所想,希望你看完之后能有更多更深入的了解

本人微信公众号(jwfy的学习分享),欢迎关注~

在开发中可能会约定一个bean使用一个不同的name,可是随着引入的第三方库越来越多,就有可能就会出现名字相同的bean。那么问题来了,多个name相同的bean,spring是如何处理的呢?是只保留第一个还是覆盖保留最后一个又或者是抛出异常明确名称不能重复,又或者业务的因素明确了不能一致的情况?接下来我们看看这个同名bean的问题。

说起同名bean,肯定要提到allowBeanDefinitionOverriding,这个关键字官方介绍是

Whether to allow re-registration of a different definition with the same name,当遇到同样的名字的时候,是否允许覆盖注册。

把代码定位到具体的位置 DefaultLiatableBeanFactory 文件

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { .... BeanDefinition oldBeanDefinition; oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { // 当发现了重名的bean之后,而且不允许出现重名bean则抛出异常 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } // 用新的bean替换之前旧的bean this.beanDefinitionMap.put(beanName, beanDefinition);....

发现几个疑问,可以实践下

  • 什么叫新的bean、如何界定
  • 如何修改allowBeanDefinitionOverriding值

如何界定新的bean

269726d687239f4deddc1c71b6d7b8a1.png
b1be6f63f38dd82aa0f96bea1b42b4c0.png

已经设置好了两个xml,各自包含了一个同名的bean,只是参数不一致而已

  • 情况1
e6f21cd387e971292ca96ac5c3824a77.png

context1.xml 在前, context.xml 在后

3d00af7c50221fa8296f101c3d8ec5f5.png
  • 情况2
1a4109ec8f580a5f3a1cf200cc1a7b7d.png

context.xml 在前, context1.xml 在后

7e41f78b49a92c07561cfd46111e569f.png

看在读取xml解析的时候同样可以知道,答案已经很明显了,spring是按照文件列表一个一个扫描注册的,所以最后保留的是后一个文件的bean

如何修改allowBeanDefinitionOverriding值

解决的思路肯定是要在真正的解析bean之前修改该值,而且要在defaultlistablebeanfactory生成之后。

protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); // 已经存在bean工厂,现在清空 } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); // 创建bean工厂 beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); // 自定义设入bean工厂的 loadBeanDefinitions(beanFactory); // 开始加载xml进行解析操作,无法修改bean工厂 synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); }}protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { if (this.allowBeanDefinitionOverriding != null) {beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); // 把Application本身的是否可覆盖bean值赋值给bean工厂 } if (this.allowCircularReferences != null) { beanFactory.setAllowCircularReferences(this.allowCircularReferences); // 赋值是否允许循环引用 }}

那么我们能够动刀的地方只能是customizeBeanFactory了,代码如下

public static void main(String[] args){ ClassPathXmlApplicationContext applicationContext =  new ClassPathXmlApplicationContext(new String[]{"context.xml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值