目录
1. 创建测试项目
2. 改变启动类所属包
3. 使用@ComponentScan
4. Spring基本扫描机制
程序通过注解告诉Spring希望哪些bean被管理,但在仅使用@Bean时已经发现,Spring需要根据五大类注解才能进一步扫描方法注解。
由此可见,Spring对注解的扫描并不是全项目扫描的,本文对Spring的基本扫描机制进行验证。
1. 创建测试项目
创建项目及Controller包、Service包、Repo包、Component包、Config包,目录结构如下:
本例测试与Controller包下的UserController类 和 Service包下的UserService类相关,
UserController类内容如下:
package com.example.iocdemo1.Controller;import org.springframework.stereotype.Controller;@Controller
public class UserController {public void doController(){System.out.println("do Controller...");}
}
UserService类内容如下:
package com.example.iocdemo1.Service;import org.springframework.stereotype.Service;@Service
public class UserService {public void doService(){System.out.println("doService...");}
}
启动类内容如下:
package com.example.iocdemo1.Controller;import com.example.iocdemo1.Service.UserService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class IoCDemo1Application {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(IoCDemo1Application.class, args);UserController controller = context.getBean(UserController.class);controller.doController();UserService userService1=context.getBean(UserService.class);userService1.doService();}
}
2. 改变启动类所属包
现将启动类移至项目包的其他子包下,以Controller包为例:
基于其他目录结构及类代码不变,重新启动程序,报错如下:
表示UserService.class这个bean没有找到(类型为UserController.class的bean获取成功,并未报错)。
在SpringBoot中有一个特点:约定大于配置。由于原始Spring项目大量的配置文件造成的不便,SpringBoot做了相关约定以简化配置。
Spring约定,从启动类所在的目录及其子孙目录开始扫描,
观察启动类首行,可见移动启动类位置后,移动类所属包:
package com.example.iocdemo1.Controller;
故而Spring默认只扫描该目录下的包及子包,可扫描到UserController,但扫描不到UserService;
3. 使用@ComponentScan
在当前启动类前增加@ComponentScan注解以指定扫描目录路径,当前若希望扫描到其他的Service包、Repo包、Component包、Config包,则需对应的路径为com.example.iocdemo1,增加注解后的启动类内容如下:
package com.example.iocdemo1.Controller;import com.example.iocdemo1.Service.UserService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;@ComponentScan("com.example.iocdemo1")
@SpringBootApplication
public class IoCDemo1Application {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(IoCDemo1Application.class, args);UserController controller = context.getBean(UserController.class);controller.doController();UserService userService1=context.getBean(UserService.class);userService1.doService();}
}
重新启动程序:
4. Spring基本扫描机制
1、根据上例,可得出Spring对注解的扫描约定如下:
默认扫描路径为启动类所在的目录及其子孙目录,可通过@ComponentScan注解指定扫描路径。
2、在项目默认配置中,并没有手动使用@ComponentScan指定扫描路径,默认扫描路径是通过启动类的@SpringBootApplication注解实现的,Alt+左点击查看注解声明:
可见@SpringBootApplication注解当中包含@ComponentScan注解。