springboot系列 @ComponentScan和@EnableAutoConfiguration的区别

研究springboot源码,在网上看相关博客的时候对@ComponentScan和@EnableAutoConfiguration两者之间的作用没有做过多的区分,导致我觉得他们两者都有扫描相关组建然后将符合要求的放入到ioc容器中。所以我就占牛角尖了,单独研究了一下他们的不同点。
@ComponentScan和@EnableAutoConfiguration都是包含在@SpringBootApplication中的,也是@SpringBootApplication中比较重要的注解。
@ComponentScan和@EnableAutoConfiguration的相同点
两者都可以将带有@Component,@Service等注解的对象加入到ioc容器中。

@ComponentScan和@EnableAutoConfiguration的不同点
1.两者虽然都能将带有注解的对象放入ioc容器中,但是它们扫描的范围是不一样的。@ComponentScan扫描的范围默认是它所在的包以及子包中所有带有注解的对象,@EnableAutoConfiguration扫描的范围默认是它所在类。
2.它们作用的对象不一样,@EnableAutoConfiguration除了扫描本类带有的注解外,还会 借助@Import的支持,收集和注册依赖包中相关的bean定义,将这些bean注入到ioc容器中,在springboot中注入的bean有两部分组成,一部分是自己在代码中写的标注有@Controller,@service,@Respority等注解的业务bean,这一部分bean就由@ComponentScan将它们加入到ioc容器中,还有一部分是springboot自带的相关bean,可以将这部分bean看成是工具bean,这部分bean就是由@EnableAutoConfiguration负责加入到容器中。
3.@EnableAutoConfiguration可以单独启动springboot项目,而@ComponentScan是不能的。

下面用代码来验证第一点和第三点


第一种情况,验证@EnableAutoConfiguration的扫描范围

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import study.springboot.component.subPackage.Food;

/**
 * @Author wangbiao
 * @Date 2019-09-01 09:49
 * @Decripition TODO
 **/
@RestController
@EnableAutoConfiguration
public class DogController {


    @RequestMapping(value = "showDog",name = "测试@Component,@EnableAutoConfiguration扫描范围")
    public String showDog(){
        return "中华田园犬";
    }


    public static void main(String[] args) {
        SpringApplication.run(DogController.class,args);
    }


}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import study.springboot.component.subPackage.Food;

/**
 * @Author wangbiao
 * @Date 2019-09-01 10:00
 * @Decripition TODO
 **/
@RestController
public class CatController {
    @RequestMapping(value = "showCat",name = "测试@Component,@EnableAutoConfiguration扫描范围")
    public String showCat(){
        return "波斯猫";
    }
}

然后用http://localhost:8080/showDog来访问,得到的结果是:

http://localhost:8080/showCat访问,得到的结果是:

得到的结果是@EnableAutoConfiguration不能将同一个包下带有注解的对象加入到ioc容器中

下面验证@EnableAutoConfiguration能否将子包中的注解对象加入到ioc容器中

import org.springframework.stereotype.Component;

/**
 * @Author wangbiao
 * @Date 2019-09-19 10:47
 * @Decripition TODO
 **/
@Component
public class Food {
    private String foodname="狗粮,猫粮";

    public String getFoodname() {
        return foodname;
    }

    public void setFoodname(String foodname) {
        this.foodname = foodname;
    }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import study.springboot.component.subPackage.Food;

/**
 * @Author wangbiao
 * @Date 2019-09-01 09:49
 * @Decripition TODO
 **/
@RestController
@EnableAutoConfiguration
public class DogController {

    @Autowired
    private Food food;
    @RequestMapping(value = "showDog",name = "测试@Component,@EnableAutoConfiguration扫描范围")
    public String showDog(){
        return "中华田园犬"+food.getFoodname();
    }


    public static void main(String[] args) {
        SpringApplication.run(DogController.class,args);
    }


}

启动就报错了:

可以看到@EnableAutoConfiguration是不能将子包中的注解对象加入到ioc容器中。
 

第二种情况,验证@Component的扫描范围
在@EnableAutoConfiguration注解上面加上@Component

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import study.springboot.component.subPackage.Food;

/**
 * @Author wangbiao
 * @Date 2019-09-01 09:49
 * @Decripition TODO
 **/
@ComponentScan
@RestController
@EnableAutoConfiguration
public class DogController {

    @Autowired
    private Food food;
    @RequestMapping(value = "showDog",name = "测试@Component,@EnableAutoConfiguration扫描范围")
    public String showDog(){
        return "中华田园犬"+food.getFoodname();
    }


    public static void main(String[] args) {
        SpringApplication.run(DogController.class,args);
    }


}

http://localhost:8080/showDog访问,结果是下面的页面,可以看出Food这个对象是被引进来了的

再用http://localhost:8080/showCat访问页面,得到的结果是下面的页面,可以看出CatController是被加入到容器中的。所以验证了第一点,@ComponentScan扫描的范围默认是它所在的包以及子包中所有带有注解的对象,@EnableAutoConfiguration扫描的范围默认是它所在类。
感谢这篇博客提供的参考:https://blog.csdn.net/qq_39404626/article/details/83995870

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章