您现在的位置是:首页 >技术杂谈 >Spring MVC Bean加载控制网站首页技术杂谈

Spring MVC Bean加载控制

一哑7 2023-05-29 00:00:03
简介Spring MVC Bean加载控制

回顾一下我们一般写的项目包括那些包吧:

  • config目录存入的是配置类,写过的配置类有:
    • ServletContainersInitConfig
    • SpringConfig
    • SpringMvcConfig
    • JdbcConfig
    • MybatisConfig
  • controller目录存放的是SpringMVC的controller类
  • service目录存放的是service接口和实现类
  • dao目录存放的是dao/Mapper接口

bean加载控制

众所周知controller、service和dao这些类都需要被容器管理成bean对象:

  • SpringMVC加载其相关bean(表现层bean),也就是controller包下的类
  • Spring控制的bean
    • 业务bean(Service)
    • 功能bean(DataSource,SqlSessionFactoryBean,MapperScannerConfigurer等)

如下图所示:
示例图

其实很简单我们只需要在SpringMVC的配置类SpringMvcConfig中使用注解@ComponentScan,我们只需要将其扫描范围设置到controller即可

在这里插入图片描述

但是新的问题出现了,因为在Spring的配置类SpringConfig中使用注解@ComponentScan,当时扫描的范围中其实是已经包含了controller
在这里插入图片描述

从包结构来看的话,Spring已经多把SpringMVC的controller类也给扫描到,所以因为功能不同,如何避免Spring错误加载到SpringMVC的bean我们继续往下看。

具体操作

解决那个我们我们很容易想到方案:加载Spring控制的bean的时候排除掉SpringMVC控制的bean。

  • 方式一:Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等
  • 方式二:Spring加载的bean设定扫描范围为com.itheima,排除掉controller包中的bean
  • 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中[我不会我跟的视频老师没讲,因为是初阶这里就不涉及了,后面想起来了我会重新回来填坑的]

我们举个例子看下,一下面项目结构为例:
在这里插入图片描述

先悄悄给大家搂一样解决方案
在这里插入图片描述

方案一

修改Spring配置类,设定扫描范围为精准范围。

@Configuration
@ComponentScan({"com.taro.service","com.taro.dao"})
public class SpringConfig {
}

当然这个例子说明可以精确指定让Spring扫描对应的包结构,真正在做开发的时候,Dao最终是交给MapperScannerConfigurer对象来进行扫描处理的,我们只需要将其扫描到service包即可。 当然现在还是推荐推荐推荐扫描一下的

方案二

方式二:修改Spring配置类,设定扫描范围为com.itheima,排除掉controller包中的bean

@Configuration
@ComponentScan(value="com.taro",
    excludeFilters=@ComponentScan.Filter(
    	type = FilterType.ANNOTATION,
        classes = Controller.class
    )
)
public class SpringConfig {
}

还记得@Configuration注解嘛,我们之前提到过,他出现的类Spring在扫描时会扫描它并加载bean

@Configuration//这里这里这里
@ComponentScan("com.taro.controller")
public class SpringMvcConfig {
}

接下来就是介绍一下我们写的那些属性都是哈了:

  • excludeFilters属性:设置扫描加载bean时,排除的过滤规则
  • type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
    • ANNOTATION:按照注解排除
    • ASSIGNABLE_TYPE:按照指定的类型过滤
    • ASPECTJ:按照Aspectj表达式排除,基本上不会用
    • REGEX:按照正则表达式排除
    • CUSTOM:按照自定义规则排除
  • classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean

当然,有了Spring的配置类,要想在tomcat服务器启动将其加载,我们需要修改ServletContainersInitConfig,还记得我们之前写的吗?

public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}

既然氛围都到这里了,不整点简单的都不好意思了;

//web配置类简化开发,仅设置配置类类名即可
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

直观的对比感受一下吧:
在这里插入图片描述
他俩是父子类哦。。。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。