spring 容器与 spring mvc 容器

此文几处有引用别人博客内容,如有侵权表示歉意!

1、spring 功能强大,其中最常用的功能 spring 是容器,是管理、产生bean的。专业术语是Ioc控制反转。spring 实例化也是通过new 关键字进行实例化,javabean 都有默认的构造器,不需要提供构造参数;spring 装载属性是通过xml文件调用bean中的setXXX方法装载相应属性值。
spring的两个核心接口BeanFactory和ApplicationContext,其中ApplicationContext 是BeanFactory类的子接口,他们都可以代表spring 容器,BeanFactory是负责配置、创建、管理Bean的,他的子接口ApplicationContext 俗称 上下文。

2、spring mvc 也是一个容器,相比spring容器相对较小,是spring 容器的子容器,spring mvc 管理Contorller bean的容器。spring mvc使用WebApplicationContext 类,该类扩展自ApplicationContext.


3、spring 容器和spring mvc 容器之间的关系:
spring 在整体框架的核心概念中,容器思想是其核心思想。 在一个项目应用中容器的个数可以是多个,spring中可以包含多个容器,其中容器之间存在层级关系。其中spring容器和spring mvc 容器就是两个容器,spring容器作为根容器,spring mvc 容器作为子容器,并且子容器可以看到父容器的Bean,父容器中不能看到子容器中的Bean.这是spring自己定义的规则。


①在 spring 配置xml文件时 配置组件扫描包,该功能扫描包下所有的@Component注解,并且自动注入到容器中,@Service、@Controller、@Repository继承自@Component。spring配置主要是为了扫描@Service和@Repository注解。配置如下:

<context:component-scan base-package="com.miniyu.test"/>

除了上诉的配置基础包扫描的方式,spring还提供了另外一种配置为<context:annotation-config base-package="con.miniyu.text"/>。如果项目中 已经配置组件扫描可以不配置注解扫描。
②在spring mvc 配置xml文件时,需要配置组件扫描包<context:component-scan base-package=""/>,主要是为了扫描@Controller,另外在spring mvc 配置文件中必须配置<mvc:annotation-driven/>,注解驱动配置是为了与@requestMapping配合使用。

HandlerMapping是spring mvc中用来处理Request请求URL到具体Controller的,其自身也分成很多种类。
HandlerAdapter是spring mvc中用来处理具体请求映射到具体方法的,其自身也分很多中类
@RequestMapping 这个注解的主要目的就是对具体的Controller和方法进行注册,以方便HandlerMapping用来处理请求映射。但是@RequestMapping必须配合<mvc:annotation-driven/>才能使用


在项目中为解决上诉容器之间的关系有如下三种方式:

  1. **(推荐)**在spring 配置扫描包指定@Service、@Repository所在包的路径,并在spring mvc 配置扫描包的指定@Controller所在包的路径,当然在spring配置扫描时也可以加入@Controller的扫描,但生成了此Bean会一直存储在spring容器中不进行使用,对资源照成浪费。总结:spring mvc容器中必须包含@Controller层级Bean,否则会请求会包404错误
  2. **(不推荐)**查看spring mvc 源码,在spring mvc 进行初始化时的执行:
protected void initHandlerMethods() {
    if (logger.isDebugEnabled()) {
       logger.debug("Looking for request mappings in application context: " + getApplicationContext());
    }
    String[] beanNames =(this.detectHandlerMethodsInAncestorContexts ?
    BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    getApplicationContext(), Object.class) :   getApplicationContext().getBeanNamesForType(Object.class));
    for (String beanName : beanNames) {
       if (isHandler(
       getApplicationContext().getType(beanName))){
                detectHandlerMethods(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }

方法**isHandler()**会判断当前的bean是否为Controller。

protected boolean isHandler(Class<?> beanType) {
        return AnnotationUtils.findAnnotation(beanType, Controller.class) != null;
    }

由于initHandlerMotheds()这个方法中handlerMethodsInitialized()主要是控制在哪个容器中获取Bean,默认是不包含父容器,我们可以修改spring mvc 配置文件,配置HandlerMapping的detectHandlerMethodsInAncestorContexts属性为true,(这里注意要根据不同的handlerMapping进行不同的配置),让其检查父容器中的Bean.

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
        <property name="detectHandlerMethodsInAncestorContexts">
            <value>true</value>
        </property>
    </bean>

3.可以让spring 容器和spring mvc容器各司其职,spring 容器只负责非@Controller的扫描注册,spring mvc 容器只进行@Controller相关Bean 的扫描注册

--Spring容器配置,排除所有@controller的Bean
<context:component-scan base-package="com.fsnip.open">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
--SpringMVC容器配置,让其只包括@controller的Bean
<context:component-scan base-package="com.fsnip.open" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT从业者的职业生涯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值