欢迎大家回到《Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《SpringMVC入门案例总结与SpringMVC工作流程分析》
入门案例的内容已经做完了,在入门案例中我们创建过一个SpringMvcConfig的配置类,再回想前面咱们学习Spring的时候也创建过一个配置类SpringConfig。这两个配置类都需要加载资源,那么它们分别都需要加载哪些内容?
我们先来看下目前我们的项目目录结构:
controller、service和dao这些类都需要被容器管理成bean对象,那么到底是该让SpringMVC加
载还是让Spring加载呢?
分析清楚谁该管哪些bean以后,接下来要解决的问题是如何让Spring和SpringMVC分开加载各自的内容。
在SpringMVC的配置类SpringMvcConfig中使用注解@ComponentScan,我们只需要将其扫描范围设置到controller即可,如
在Spring的配置类SpringConfig中使用注解@ComponentScan ,当时扫描的范围中其实是已经包含
了controller,如:
从包结构来看的话,Spring已经多把SpringMVC的controller类也给扫描到,所以针对这个问题
该如何解决,就是咱们接下来要学习的内容。
概况的描述下咱们现在的问题就是因为功能不同,如何避免Spring错误加载到SpringMVC的bean?
针对上面的问题,解决方案也比较简单,就是:
具体该如何排除,有两种方式来解决:
4.0.0 com.itheima springmvc_02_bean_load 1.0-SNAPSHOT war 54 55 19 javax.servlet javax.servlet-api 163.1.0 17provided 1820 24org.springframework 21spring-webmvc 225.2.10.RELEASE 2325 29 30com.alibaba 26druid 271.1.16 2831 35 36org.mybatis 32mybatis 333.5.6 3437 41 42mysql 38mysql-connector-java 395.1.47 4043 47 48org.springframework 44spring-jdbc 455.2.10.RELEASE 4649 53org.mybatis 50mybatis-spring 511.3.0 5256 6857 6758 66org.apache.tomcat.maven 59tomcat7-maven-plugin 602.1 6165 80 63/ 64
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer { 2 protected WebApplicationContext createServletApplicationContext() { 3 AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); 4 ctx.register(SpringMvcConfig.class); 5 return ctx; 6 } 7 protected String[] getServletMappings() { 8 return new String[]{"/"}; 9 } 10 protected WebApplicationContext createRootApplicationContext() { 11 return null; 12 } 13 } 14 15 @Configuration 16 @ComponentScan("com.itheima.controller") 17 public class SpringMvcConfig { 18 } 19 20 @Configuration 21 @ComponentScan("com.itheima") 22 public class SpringConfig { 23 }
@Controller 2 public class UserController { 3 4 @RequestMapping("/save") 5 @ResponseBody 6 public String save(){ 7 System.out.println("user save ..."); 8 return "{'info':'springmvc'}"; } } public interface UserService { public void save(User user); } @Service public class UserServiceImpl implements UserService { public void save(User user) { System.out.println("user service ..."); } } public interface UserDao { @Insert("insert into tbl_user(name,age)values(#{name},#{age})") public void save(User user); } public class User { private Integer id; private String name; private Integer age; //setter..getter..toString略 }
方式一:修改Spring配置类,设定扫描范围为精准范围。
@Configuration @ComponentScan({"com.itheima.service","comitheima.dao"}) public class SpringConfig { }
说明:
上述只是通过例子说明可以精确指定让Spring扫描对应的包结构,真正在做开发的时候,因为Dao最终是交给MapperScannerConfigurer对象来进行扫描处理的,我们只需要将其扫描到service包即可。
方式二:修改Spring配置类,设定扫描范围为com.itheima,排除掉controller包中的bean
@Configuration @ComponentScan(value="com.itheima", excludeFilters=@ComponentScan.Filter( type = FilterType.ANNOTATION, classes = Controller.class ) ) public class SpringConfig { }
大家只需要知道第一种ANNOTATION即可
如何测试controller类已经被排除掉了
public class App{ public static void main (String[] args){ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); System.out.println(ctx.getBean(UserController.class)); } }
如果被排除了,该方法执行就会报bean未被定义的错误
出现问题的原因是,
最后一个问题,有了Spring的配置类,要想在tomcat服务器启动将其加载,我们需要修改ServletContainersInitConfig
1 public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer { 2 protected WebApplicationContext createServletApplicationContext() { 3 AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); 4 ctx.register(SpringMvcConfig.class); 5 return ctx; 6 } 7 protected String[] getServletMappings() { 8 return new String[]{"/"}; 9 } 10 protected WebApplicationContext createRootApplicationContext() { 11 AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); 12 ctx.register(SpringConfig.class); 13 return ctx; 14 } 15 }
对于上述的配置方式,Spring还提供了一种更简单的配置方式,可以不用再去创建AnnotationConfigWebApplicationContext对象,不用手动register对应的配置类,如何实现?
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[]{"/"}; } }
名称 | @ComponentScan |
---|---|
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置spring配置类扫描路径,用于加载使用注解格式定义的bean |
相关属性 | excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)和具体项(classes)includeFilters:加载指定的bean,需要指定类别(type)和具体项(classes) |