基於spring同名bean覆蓋問題的解決
spring同名bean覆蓋問題
默認情況下,spring在處理同一個ApplicationContext中名稱相同的bean時
分為兩種情況處理
1、如果兩個bean是在同一個配置文件中,那麼spring會報錯。
2、如果兩個bean是在不同的配置文件中,默認情況下,spring會覆蓋先前的bean。
在配置文件很多時,如果在啟動時,對於同名的bean加載沒有異常信息,出現問題後會比較難以定位。
在spring中,處理容器的元數據信息時,默認使用DefaultListableBeanFactory類,該類中有個屬性:allowBeanDefinitionOverriding,默認情況下為true,即允許重名的bean可以被覆蓋。
還好,spring有辦法對改屬性賦值。
重寫ContextLoaderListener,對於web應用,容器類型為XmlWebApplicationContext,在該類中設置allowBeanDefinitionOverriding為false,然後在spring啟動時,碰到同名bean就會拋出異常。
案例如下
public class TradeContextLoaderListener extends ContextLoaderListener { @Override protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) { super.customizeContext(servletContext, applicationContext); XmlWebApplicationContext context = (XmlWebApplicationContext) applicationContext; context.setAllowBeanDefinitionOverriding(false); } }
配置web.xml:
<listener> <description>spring監聽器</description> <listener-class>com.***.trade.system.web.util.TradeContextLoaderListener</listener-class> </listener>
spring 子類覆蓋父類中註入的bean
我們在設計程序框架的時候,會設計一個抽象基類,子類繼承這個基類,共有的方法放到基類中去,使用spring後使代碼變的很簡單,現在遇到的問題是在基類中註入bean後,子類不可能都會是有這個bean,那麼需要考慮到子類需要覆蓋或者說重新註入個性化的bean
有三種方法來實現這個效果,以下是一種方法,如下面代碼:
抽象基類
public abstract class AbstractNameService { public abstract String getname(); }
兩個實現類:
@Service("firstNameService") public class FirstNameService extends AbstractNameService { @Override public String getname() { return "FirstName"; } }
@Service("nameService") public class NameService extends AbstractNameService { @Override public String getname() { return "Name"; } }
另外一個抽象基類
public abstract class AbstractService { protected AbstractNameService nameService; public String getName() { return nameService.getname(); } public AbstractNameService getService() { return nameService; } <span style="color:#ff9966;">@Resource(name = "nameService")</span> public void setService(AbstractNameService nameService) { this.nameService = nameService; } }
實現類:
@Service("getNameService") public class GetNameService extends AbstractService { <span style="color:#ff9900;">@Resource(name = "firstNameService")</span> @Override public void setService(AbstractNameService nameService) { this.nameService = nameService; } }
controller
@Controller public class UnionpayQuickPayDSMVC { @Resource private AbstractService getNameService; @RequestMapping(value = "/*", method = RequestMethod.GET) public void execute(HttpServletRequest request, HttpServletResponse response) { try { response.getWriter().write(getNameService.getName()); } catch (IOException e) { System.out.println(e); } } }
在applicationContext.xml和springmvc的配置文件隻需要添加一個包<context:component-scan/>標簽就行瞭
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 基於Spring上下文工具類 ApplicationContextUtil
- 獲取Spring的上下文環境ApplicationContext的最簡單方式
- 關於spring中單例Bean引用原型Bean產生的問題及解決
- 詳解Spring bean的註解註入之@Autowired的原理及使用
- Spring五大類註解讀取存儲Bean對象的方法