其他分享
首页 > 其他分享> > spring – 分层上下文的范围

spring – 分层上下文的范围

作者:互联网

我读过了:

Multiple component-scan

What is the difference between ApplicationContext and WebApplicationContext in Spring MVC?

@RequestMapping annotation not working if <context:component-scan /> is in application context instead of dispatcher context(稍后会详细介绍)

和其他几个但这些都没有回答这个问题:

为什么< context:component-scan ... />的范围?当它出现在Spring MVC应用程序的ROOT上下文中时有限制吗?

我的理解是它会导致扫描指定包中的所有类,并实例化任何使用@Component或其任何子构造型(@ Repository,@ Service和@Controller)构造的bean.

鉴于:

applicationContext.xml(根上下文)

<beans...>
    ...
    <context:component-scan base-package="com.myproject"/>
    <context:property-placeholder 
               ignore-resource-not-found="true" 
               location="classpath:default.properties, file:///etc/gallery/gallery.properties"/>
</beans>

main-servlet.xml(servlet上下文)

<beans ...>
    ...
    <mvc:annotation-driven/>
    <mvc:resources mapping="/image/**"   location="file:/${gallery.location}" />
    <mvc:resources mapping="/css/**"     location="/css/"/>
    <mvc:resources mapping="/js/**"      location="/js/"/>
    <mvc:resources mapping="/images/**"  location="/images/"/>
    ...
</beans>

COM / myproject的/ WEB / MainController.java

package com.myproject.web;
@Controller
public class MainController 
{
    ...

    @RequestMapping("/gallery/**")
    public String gallery(ModelMap modelMap, HttpServletRequest req, HttpServletResponse resp) throws IOException
    {
        ...
    }
}

Spring文档声明在根上下文中实例化的任何bean都是共享的,并且可供各个servlet应用程序上下文使用.因此,两个< context:...>根上下文中的声明应该导致在servlet上下文中可见的bean.但事实并非如此.我需要重复BOTH< context:component-scan ... />和< context:property-placeholder ... />在servlet上下文中.

省略< context:component-scan ... />在servlet上下文中导致

Sep 15, 2015 10:08:16 AM org.springframework.web.servlet.PageNotFound noHandlerFound
WARNING: No mapping found for HTTP request with URI [/gallery/habitat/20150813] in DispatcherServlet with name 'main'
Sep 15, 2015 10:08:16 AM org.springframework.web.servlet.PageNotFound noHandlerFound
WARNING: No mapping found for HTTP request with URI [/error] in DispatcherServlet with name 'main'

表明@Controller没有解决.

省略< context:property-placeholder ... />使用未处理的属性引用导致@Value注释,在我的情况下导致一些损坏的链接.

由于这两个< context:... />指令导致bean实例化,我很困惑为什么bean在子上下文中不可见,与文档直接矛盾.另外,没有两个组件扫描语句导致控制器bean被实例化两次?

关于@RequestMapping annotation not working if <context:component-scan /> is in application context instead of dispatcher context,我确实有< mvc:annotation-driven />在我的应用程序上下文中,这里的答案没有解释为什么需要两个组件扫描语句.

我真的很不舒服使用“魔法”,除非我完全理解它是如何工作的,并且可以预测当我调整某些东西时它会如何表现.所以“只需将它添加到两个地方并继续前进”的“解决方案”是不可接受的.

解决方法:

< context:property-placeholder />

< context:property-placeholder />注册一个PropertySourcesPlaceholderConfigurer,它是一个[BeanFactoryPostProcessor].这里的关键是BeanFactory,它在BeanFactory上运行(ApplicationContext就是这样的东西).确切地说,它在BeanFactory上运行,它定义在.不在父或子上下文中.因此,您需要在两种情况下注册它.

有两个相同的< context:property-placeholder />有一个缺点.两者都将加载相同的资源,并最终加载相同的属性文件两次.要消除这种情况,请结合< context:property-placeholder />使用< util:properties />元件.后者加载属性文件并在上下文中将它们公开为bean,您可以将此bean连接到< context:property-placeholder />使用properties-ref属性.您只在根上下文中加载属性,并在子上下文中简单地引用它们.

根上下文

<util:properties id="appProperties" location="classpath:default.properties, file:///etc/gallery/gallery.properties" ignore-resource-not-found="true" />
<context:property-placeholder properties-ref="appProperties" />

儿童语境

<context:property-placeholder properties-ref="appProperties" />

< mvc:annotation-driven />

关于< mvc:annotation-driven />其中包括RequestMappingHandlerMapper,这个bean负责检测在@Controller注释类中使用@RequestMapping注释的方法.默认情况下,它在ApplicationContext中执行此操作,它在父上下文中的NOT中定义.您可以将detectHandlerMethodsInAncestorContexts属性设置为true以实现此目的.

根据经验,您可以说您的根上下文应该包含所有应用程序全局,如服务,存储库,基础架构bean,如数据源等.子上下文(由DispatcherServlet加载应该只包含Web相关材料,如@Controllers.).

只需复制粘贴< context:component-scan />,从根本上复制它,是一个糟糕的(非常糟糕的)想法.因为这将导致两次实例化所有bean,并可能导致事务,内存等问题.因为像< tx:annotation-driven />这样的事情.使用BeanFactoryPostProcessor和BeanPostProcessor也可以使用AOP和AOP,就像属性支持一样.

根上下文

<context:component-scan base-package="com.myproject">
    <context:exclude-filters type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

儿童语境

<context:component-scan base-package="com.myproject" use-default-filters="false">
    <context:include-filters type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

标签:spring-mvc,spring,property-placeholder,spring-ioc,component-scan
来源: https://codeday.me/bug/20190623/1272390.html