Let’s review the packages we generally write about:
- The configuration class is stored in the config directory, and the configuration classes written are:
- ServletContainersInitConfig
- SpringConfig
- SpringMvcConfig
- JdbcConfig
- MybatisConfig
- The controller directory stores the controller class of SpringMVC
- The service directory stores the service interface and implementation class
- The dao directory stores the dao/Mapper interface
bean loading control
It is well known that classes such as controller, service and dao need to be managed by the container as bean objects:
- SpringMVC loads its related beans (presentation layer beans), which are classes under the controller package
- Spring-controlled beans
- Business bean (Service)
- Functional beans (DataSource, SqlSessionFactoryBean, MapperScannerConfigurer, etc.)
As shown below:
In fact, it is very simple. We only need to SpringMvcConfig
use annotations in the configuration class of SpringMVC @ComponentScan
, and we only need to set its scanning range to the controller.
But a new problem arises, because SpringConfig
the annotation is used in the Spring configuration class @ComponentScan
, the controller is actually included in the scope of the scan at that time
From the perspective of the package structure, Spring has already scanned the controller class of SpringMVC, soBecause of the different functions, how to avoid Spring wrongly loading beans into SpringMVCLet's continue reading.
Concrete operation
To solve that, we can easily think of a solution: exclude the beans controlled by SpringMVC when loading the beans controlled by Spring.
- Method 1: The bean loaded by Spring sets the scanning range to a precise range, such as service package, dao package, etc.
- Method 2: The bean loaded by Spring sets the scan range to com.itheima, and excludes the bean in the controller package
- Method 3: Do not distinguish between Spring and SpringMVC environments, and load them into the same environment ]
Let's take a look at an example, take the following project structure as an example:
First quietly give everyone the same solution
Option One
Modify the Spring configuration class and set the scanning range to the precise range.
@Configuration
@ComponentScan({
"com.taro.service","com.taro.dao"})
public class SpringConfig {
}
Of course, this example shows that you can precisely specify the corresponding package structure for Spring to scan. When actually doing development,Dao is finally handed over to MapperScannerConfigurer
the object for scanning and processing, we only need to scan it to the service package.Of course it still is 推荐推荐推荐扫描一下的
.
Option II
Method 2: Modify the Spring configuration class, set the scanning range to com.iheima, and exclude the beans in the controller package
@Configuration
@ComponentScan(value="com.taro",
excludeFilters=@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
Remember the @Configuration annotation, as we mentioned before, the class Spring that appears in it will scan it and load the bean when scanning
@Configuration//这里这里这里
@ComponentScan("com.taro.controller")
public class SpringMvcConfig {
}
The next step is to introduce the attributes we wrote:
- excludeFilters attribute: set the exclusion filtering rules when scanning and loading beans
- type attribute: set the exclusion rules, currently use the annotation type when the bean is defined to exclude
- ANNOTATION: exclude by annotation
- ASSIGNABLE_TYPE: filter according to the specified type
- ASPECTJ: Excluded according to Aspectj expression, basically not used
- REGEX: exclude by regular expression
- CUSTOM: Exclude according to custom rules
- classes attribute: set the specific annotation class to be excluded, and the current setting excludes the beans defined by @Controller
Of course, with the Spring configuration class, we need to modify ServletContainersInitConfig if we want to load it when the tomcat server starts. Remember what we wrote before?
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[]{
"/"};
}
}
Now that the atmosphere is here, it’s embarrassing if it’s not simple;
//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[]{
"/"};
}
}
Let’s feel the intuitive comparison:
they are father and son. . .