歡迎和大家交流技術相關問題:
郵箱: jiangxinnju@163.com
博客園地址: http://www.cnblogs.com/jiangxinnju
GitHub地址: https://github.com/jiangxincode
知乎地址: https://www.zhihu.com/people/jiangxinnju
今天處理了一個問題,J2EE項目依賴了底層平台的功能,平台JAR包中配置了一個Bean,對應的實現類也在該平台JAR包中,由於Bean的配置不是懶加載的,所以在Tomcat容器啟動時就會調用該Bean對應實現類中的init方法,但是該方法會對我們的業務產生副作用。現在想屏蔽這種副作用,我們肯定不能要求底層平台去修改代碼,去除該Bean。所以考慮采取hack的方法解決。
我們在我們的項目目錄中新建了一個*.service.xml
文件,然后在該文件中重新配置了一下這個Bean,配置內容與平台JAR包中的配置相同,僅是把實現類修改為我們自己的類,這個類是一個空實現,也就避免了對業務產生副作用。然后在web.xml
中的contextConfigLocation參數中,將我們自己的*.service.xml
所在路徑配置到平台JAR包中的Bean配置文件之后,也就是說我們的配置文件優先級更高。這樣的話Spring容器在掃描過程中會掃描所有的配置文件,先掃描到平台JAR包中的配置文件,然后掃描到我們自定義的*.service.xml
文件,發現同一個bean-id有兩個配置,默認情況下會使用后面的覆蓋前面的Bean定義,然后調用優先級更高的實現類進行初始化。
經過測試,結果和預期一致。
其實還應該有一個方法,就是不修改web.xml
文件也不添加*.service.xml
文件,而是在自己的項目中添加一個包路徑和類名與JAR包中Bean的實現類完全相同的空實現類,然后將該項目打包到遠程服務器上的時候一定要保證自己的JAR包比平台JAR包先加載到,有兩個辦法:如果兩個JAR包在同一個目錄下,要保證自己的JAR包的名稱在所處的文件系統中的自動排序靠前;如果兩個JAR包不在同一個目錄,要保證自己的JAR包所在的目錄靠前。當然這都是在沒有特殊指定classpath的情況下,如果可以指定classpath,則靈活性更大。
當然雖然解決了底層平台副作用的問題,但是最好的方式是將自己的業務和平台解耦,盡量避免這種副作用問題。另外如果必須采用hack的方法解決問題,一定要在相關文件中寫清注釋。