利用Spring中同名Bean相互覆盖的特性,定制平台的类内容。

时间:2022-04-25
本文章向大家介绍利用Spring中同名Bean相互覆盖的特性,定制平台的类内容。,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

今天处理了一个问题,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的方法解决问题,一定要在相关文件中写清注释。