spring_使用Spring MVC时的常见错误

spring

spring

spring_framework
大约10年前我开始我的职业生涯时,Struts MVC就是市场上的常态。 但是,多年来,我观察到Spring MVC逐渐流行起来。 鉴于Spring MVC与Spring容器的无缝集成以及它提供的灵活性和可扩展性,这对我来说并不奇怪。

从到目前为止的Spring旅程中,我通常会看到人们在配置Spring框架时犯了一些常见的错误。 与人们仍然使用Struts框架的时间相比,这种情况发生的频率更高。 我想这是灵活性和可用性之间的权衡。 另外,Spring文档中有很多示例,但缺乏解释。 为了填补这一空白,本文将尝试阐述和解释我经常看到的3个常见问题。

在Servlet上下文定义文件中声明bean

因此,我们每个人都知道Spring使用ContextLoaderListener加载Spring应用程序上下文。 不过,当宣布DispatcherServlet我们需要创建名称为“ $ {servlet.name} -context.xml”的servlet上下文定义文件。 有没有想过为什么?

应用程序上下文层次结构

并非所有开发人员都知道Spring应用程序上下文具有层次结构。 让我们看一下这种方法:

org.springframework.context.ApplicationContext.getParent()

它告诉我们Spring Application Context具有父级。 那么,这个父母干什么呢?

如果下载源代码并进行快速引用搜索,则应该发现Spring Application Context将parent作为其扩展名。 如果您不介意阅读代码,请让我向您展示方法BeanFactoryUtils.beansOfTypeIn includedAncestors()中的用法示例:

if (lbf instanceof HierarchicalBeanFactory) {
    HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
    if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
 Map parentResult = 
              beansOfTypeIncludingAncestors((ListableBeanFactory) hbf.getParentBeanFactory(), type);
 ...
    }
}
return result;
}

如果遍历整个方法,您将发现在搜索父上下文之前,Spring Application Context会扫描以在内部上下文中查找bean。 通过这种策略,Spring Application Context将有效地进行反向广度优先搜索以查找bean。

ContextLoaderListener

这是每个开发人员都应该知道的众所周知的类。 它有助于从预定义的上下文定义文件中加载Spring应用程序上下文。 由于其实现ServletContextListener因此将在加载Web应用程序后立即加载Spring应用程序上下文。 当加载包含带有@PostContruct批注或批处理作业的bean的Spring容器时,这带来了无可争议的好处。

相反,在初始化servlet之前,不会构造servlet上下文定义文件中的任何bean定义。 何时初始化Servlet? 这是不确定的。 在最坏的情况下,您可能需要等到用户对servlet映射URL进行第一次点击才能加载spring上下文。

根据以上信息,您应该在哪里声明所有珍贵的豆子? 我觉得这样做的最佳位置是ContextLoaderListener加载的上下文定义文件,而没有其他地方。 这里的技巧是将ApplicationContext作为servlet属性存储在键org.springframework.web.context.WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE下稍后, DispatcherServlet将从ServletContext加载此上下文,并将其分配为父应用程序上下文。

protected WebApplicationContext initWebApplicationContext() {
   WebApplicationContext rootContext =
      WebApplicationContextUtils.getWebApplicationContext(getServletContext());
   ...
}

由于这种行为,强烈建议创建一个空的servlet应用程序上下文定义文件,并在父上下文中定义您的bean。 这将有助于避免在加载Web应用程序时重复创建Bean,并确保立即执行批处理作业。

从理论上讲,在servlet应用程序上下文定义文件中定义bean会使该bean唯一且仅对该servlet可见。 但是,在使用Spring的8年中,除了定义Web Service端点之外,几乎没有发现此功能的任何用途。

这是一个小错误,但是如果您不注意它,它将引起您的注意。 Log4jConfigListener是我在-Dlog4j.configuration首选的解决方案,我们可以控制的log4j加载不改变服务器的引导过程。

显然,这应该是在web.xml中声明的第一个侦听器。 否则,您浪费所有的时间来声明正确的日志记录配置。

由于对Bean的探索管理不善而复制了Bean

在Spring的初期,开发人员在xml文件上打字的时间比Java类花费的时间更多。 对于每个新bean,我们需要自己声明和连接依赖项,这是干净,整洁但非常痛苦的。 毫无疑问,Spring框架的更高版本向更高的可用性发展。 如今,开发人员可能只需要声明事务管理器,数据源,属性源,Web服务端点,其余的就可以进行组件扫描和自动装配。

我喜欢这些新功能,但是这种强大的力量需要承担巨大的责任。 否则,事情会很快变得混乱。 XML文件中的组件扫描和bean声明是完全独立的。 因此,如果对bean进行注释以进行组件扫描并手动进行声明,则在bean容器中完全可能具有相同类的相同bean。 幸运的是,这种错误应该只发生在初学者身上。

当我们需要将一些嵌入式组件集成到最终产品中时,情况变得更加复杂。 然后,我们确实需要一种策略来避免重复的bean声明。

spring_component

上图显示了我们日常生活中遇到的种种现实问题。 大多数情况下,系统是由多个组件组成的,通常,一个组件可为多个产品提供服务。 每个应用程序和组件都有自己的bean。 在这种情况下,最好的声明方式是避免重复的bean声明?

这是我建议的策略:

  • 确保每个组件都必须以专用的软件包名称开头。 当我们需要进行组件扫描时,它使我们的生活变得更加轻松。
  • 不要指示开发组件的团队采用在组件本身中声明Bean(注释与xml声明)的方法。 开发人员负责将组件打包到最终产品中,以确保没有重复的bean声明。
  • 如果组件中包含上下文定义文件,请给它一个包,而不是放在classpath的根目录中。 给它起一个特定的名字甚至更好。 例如, src / main / resources / spring-core / spring-core-context.xmlsrc / main / resource / application-context.xml更好 想象一下,如果在相同的程序包中打包几个包含相同文件application-context.xml的组件,那该怎么办!
  • 如果您已经在一个上下文文件中声明了bean,则不要为组件扫描提供任何注释( @ Component, @ Service@Repository )。
  • 将特定于环境的bean(例如data-sourceproperty-source)拆分到一个单独的文件中并重用。
  • 不要在常规包装上进行组件扫描。 例如,如果不扫描org.springframework.coreorg.springframework.contextorg.springframework.ui等几个子程序包,则比扫描org.springframework程序包更容易管理。

结论

希望以上技巧对日常使用很有帮助。 如有任何疑问或任何其他想法,请发送反馈以提供帮助。

翻译自: https://www.javacodegeeks.com/2014/07/common-mistakes-when-using-spring-mvc.html

spring

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值