@ServeletComponentScan和@ComponentScan的區別


 

一、SpringBoot中使用Servlet
在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通過@WebServlet、@WebFilter、@WebListener注解自動注冊,無需其他代碼。

1.在入口Application類上加入注解@ServletComponentScan

  1.  
    package com.hui;
  2.  
     
  3.  
    import org.springframework.boot.SpringApplication;
  4.  
    import org.springframework.boot.autoconfigure.SpringBootApplication;
  5.  
    import org.springframework.boot.web.servlet.ServletComponentScan;
  6.  
     
  7.  
    @SpringBootApplication
  8.  
    @ServletComponentScan
  9.  
    public class Application {
  10.  
     
  11.  
    public static void main(String[] args) {
  12.  
    SpringApplication.run(Application.class, args);
  13.  
    }
  14.  
    }


2.新建Servlet類,繼承HttpServlet並且加入注解@WebServlet(name=“TestServlet”,urlPatterns="/test")

  1.  
    package com.hui.qiang;
  2.  
     
  3.  
    import java.io.IOException;
  4.  
     
  5.  
    import javax.servlet.ServletException;
  6.  
    import javax.servlet.annotation.WebServlet;
  7.  
    import javax.servlet.http.HttpServlet;
  8.  
    import javax.servlet.http.HttpServletRequest;
  9.  
    import javax.servlet.http.HttpServletResponse;
  10.  
     
  11.  
    @WebServlet(name= "TestServlet",urlPatterns= "/test")
  12.  
    public class TestServlet extends HttpServlet {
  13.  
     
  14.  
    private static final long serialVersionUID = 1L;
  15.  
     
  16.  
    @Override
  17.  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  18.  
    throws ServletException, IOException {
  19.  
    System.out.println( "doGet");
  20.  
    }
  21.  
    }


3.之后運行代碼,在瀏覽器地址欄輸入http://localhost:8080/test,若看到控制台打印doGet,則表示Servlet創建成功。
注意:
(1)如果不加@ServletComponentScan注解則會報404即找不到頁面,控制台也掃描不到我們配置的servlet:/test,即無法被映射
(2)如果Application類和Servlet類不在同一包下,則@ServletComponentScan需要添加相應的路徑,如Application類在包com.hui.xiao下,則寫為@ServletComponentScan(“com.hui.xiao”)或@ServletComponentScan(“com.hui”)

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

二、Spring, Spring Boot中的@ComponentScan注解用法介紹
@ComponentScan
如果你理解了ComponentScan,你就理解了Spring.
Spring是一個依賴注入(dependency injection)框架。所有的內容都是關於bean的定義及其依賴關系。
定義Spring Beans的第一步是使用正確的注解-@Component或@Service或@Repository.
但是,Spring不知道你定義了某個bean除非它知道從哪里可以找到這個bean.
ComponentScan做的事情就是告訴Spring從哪里找到bean

由你來定義哪些包需要被掃描。一旦你指定了,Spring將會將在被指定的包及其下級的包(sub packages)中尋找bean
下面分別介紹在Spring Boot項目和非Spring Boot項目(如簡單的JSP/Servlet或者Spring MVC應用)中如何定義ComponentScan

注:@ComponentScan的不同寫法
1.@ComponentScan({“com.xiao.hui”,“com.xiao.qiang”})或@ComponentScan(basePackages = {“com.xiao.hui”,“com.xiao.qiang”})
2.@ComponentScan(“com.xiao”)或@ComponentScan(value = “com.xiao”)或@ComponentScan(basePackages = { “com.xiao” })
3.@ComponentScan(basePackageClasses=要掃描類.class所在位置的包) 意思是要掃描哪個類所在的包,如@ComponentScan(basePackageClasses=hehe.class),這種寫法不如上面的那種寫法好有局限性

Spring Boot項目
總結:
1.SpringBoot在寫啟動類的時候如果不使用@ComponentScan指明對象掃描范圍,默認指掃描當前啟動類所在的包里的對象,如果你的其他包都在使用了@SpringBootApplication注解的主類所在的包及其下級包,則你什么都不用做,SpringBoot會自動幫你把其他包都掃描了。為了方便,我一般都把主類放在了所有類的上一級包中,如項目所有的class文件都放在了包com.beauty的下級包中,則把spring boot的主類放在包com.beauty下。
2.如果當前啟動類沒有包,則在啟動時會報錯:Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package錯誤,因為啟動類不能直接放在main/java文件夾下,必須要建一個包把它放進去或者使用@ComponentScan指明要掃描的包。
3.如果你有一些bean所在的包,不在主類的包及其下級包,那么你需要手動加上@ComponentScan注解並指定那個bean所在的包。

舉個栗子,看下面定義的類:

  1.  
    package com.xiao.qiang.qianming;
  2.  
     
  3.  
    import org.springframework.boot.SpringApplication;
  4.  
    import org.springframework.boot.autoconfigure.SpringBootApplication;
  5.  
    import org.springframework.context.ApplicationContext;
  6.  
    import org.springframework.context.ConfigurableApplicationContext;
  7.  
     
  8.  
    @ SpringBootApplication
  9.  
    public class SpringbootApplication {
  10.  
     
  11.  
    public static void main( String[] args) {
  12.  
    ApplicationContext applicationContext =
  13.  
    SpringApplication.run( SpringbootApplication. class, args);
  14.  
     
  15.  
    for ( String name : applicationContext.getBeanDefinitionNames()) {
  16.  
    System.out. println(name);
  17.  
    }
  18.  
    }
  19.  
    }


類SpringbootApplication在com.xiao.qiang.qianming包下,這個類使用了@SpringBootApplication注解,該注解定義了Spring將自動掃描包com.xiao.qiang.qianming及其子包下的bean
如果你項目中所有的類都定義在上面的包及其子包下,那你不需要做任何事。
但假如你一個類定義在包com.xiao.hui下,則你需要將這個新包也納入掃描的范圍,有兩個方案可以達到這個目的。

方案1
定義@ComponentScan(“com.xiao”),這么做掃描的范圍擴大到整個父包com.xiao

  1.  
    @ComponentScan("com.xiao")
  2.  
    @SpringBootApplication
  3.  
    public class SpringbootIn10StepsApplication {


方案2
定義分別掃描兩個包

  1.  
    @ ComponentScan({" com .xiao .hui"," com .xiao .qiang"})
  2.  
    @ SpringBootApplication
  3.  
    public class SpringbootIn10StepsApplication {


非Spring Boot項目
在非Spring Boot項目中,我們必須顯式地使用@ComponentScan注解定義被掃描的包,可以通過XML文件在應用上下文中定義或在Java代碼中對應用上下文定義

Java代碼方式:

  1.  
    @ ComponentScan({" com .xiao .package1"," com .xiao .package2"})
  2.  
    @ Configuration
  3.  
    public class SpringConfiguration {


注:@Configuration 和@ComponentScan注解背后會做什么呢?
其實很簡單,@ComponentScan告訴Spring 哪個packages 的用注解標識的類 會被spring自動掃描並且裝入bean容器。
例如,如果你有個類用@Controller注解標識了,那么,如果不加上@ComponentScan,自動掃描該controller,那么該Controller就不會被spring掃描到,更不會裝入spring容器中,因此你配置的這個Controller也沒有意義。
類上的注解@Configuration 是最新的用注解配置spring,也就是說這是個配置文件,和原來xml配置是等效的,只不過現在用java代碼進行配置了 加上一個@Configuration注解就行了,是不是很方便,不需要那么繁瑣的xml配置了,這樣基於注解的配置,可讀性也大大增高了。

XML文件方式:
<context:component-scan base-package=“com.xiao.package1, com.xiao.package2” />
 

三、使用@ComponentScan自動掃描組件實例
包掃描會掃描只要標注了@Controller,@Service,@Repository,@Component這四個注解都會被掃描到容器中。
1、@Controller 控制器(注入服務)
用於標注控制層,相當於struts中的action層
2、@Service 服務(注入dao)
用於標注服務層,主要用來進行業務的邏輯處理
3、@Repository(實現dao訪問)
用於標注數據訪問層,也可以說用於標注數據訪問組件,即DAO組件.
4、@Component (把普通pojo實例化到spring容器中,相當於配置文件中的 )
泛指各種組件,就是說當我們的類不屬於各種歸類的時候(不屬於@Controller、@Services等的時候),我們就可以使用@Component來標注這個類。
案例:<context:component-scan base-package=”com.*”>
上面的這個例子是引入Component組件的例子,其中base-package表示為需要掃描的所有子包。
有一篇不錯的文章(Spring注解詳解):https://blog.csdn.net/xyh820/article/details/7303330/

å¨è¿éæå¥å¾çæè¿°
新增控制層的java類:TestController和HelloController

  1.  
    import org.springframework.stereotype.Controller;
  2.  
     
  3.  
    @Controller
  4.  
    public class TestController {
  5.  
     
  6.  
    }

 

  1.  
    import org .springframework .web .bind .annotation .RequestMapping;
  2.  
    import org .springframework .web .bind .annotation .RequestMethod;
  3.  
    import org .springframework .web .bind .annotation .RestController;
  4.  
     
  5.  
    @ RestController
  6.  
    public class HelloController {
  7.  
    @ RequestMapping( value="/ hello", method = RequestMethod.GET)
  8.  
    public String hello() {
  9.  
    return " Hello, Spring Boot";
  10.  
    }
  11.  
    }


新建一個業務邏輯層類:TestService

  1.  
    import org.springframework.stereotype.Service;
  2.  
     
  3.  
    @Service
  4.  
    public class TestService {
  5.  
     
  6.  
    }


新建一個數據庫連接Dao類:TestDao

  1.  
    import org.springframework.stereotype.Repository;
  2.  
     
  3.  
    @Repository
  4.  
    public class TestDao {
  5.  
     
  6.  
    }


新建一個Person:

  1.  
    public class Person {
  2.  
    public Person(String string, int i) {
  3.  
    }
  4.  
    }


主方法測試:
spring boot:

  1.  
    import org.springframework.boot.SpringApplication;
  2.  
    import org.springframework.boot.autoconfigure.SpringBootApplication;
  3.  
    import org.springframework.context.ApplicationContext;
  4.  
    import org.springframework.context.annotation.ComponentScan;
  5.  
     
  6.  
    @ SpringBootApplication
  7.  
    @ ComponentScan(value = "com.hui")
  8.  
    public class Application {
  9.  
     
  10.  
    public static void main( String[] args) {
  11.  
    ApplicationContext applicationContext =
  12.  
    SpringApplication.run( Application. class, args);
  13.  
     
  14.  
    for ( String name : applicationContext.getBeanDefinitionNames()) {
  15.  
    System.out. println(name);
  16.  
    }
  17.  
    }
  18.  
    }


非spring boot:

  1.  
    import org.springframework.context.ApplicationContext;
  2.  
    import org.springframework.context. annotation.AnnotationConfigApplicationContext;
  3.  
    import org.springframework.context. annotation.Bean;
  4.  
    import org.springframework.context. annotation.ComponentScan;
  5.  
    import org.springframework.context. annotation.Configuration;
  6.  
     
  7.  
    import com.hui.entity.Person;
  8.  
     
  9.  
    @Configuration
  10.  
    @ComponentScan(value = "com.hui")
  11.  
    public class ComponentTest {
  12.  
     
  13.  
    @Bean
  14.  
    public Person getPerson() {
  15.  
    return new Person( "百度好帥", 10000);
  16.  
    }
  17.  
     
  18.  
    public static void main(String[] args) {
  19.  
    @SuppressWarnings("resource")
  20.  
    ApplicationContext applicationContext =
  21.  
    new AnnotationConfigApplicationContext(ComponentTest. class);
  22.  
    String[] beanNames = applicationContext.getBeanDefinitionNames();
  23.  
    for (String bean : beanNames) {
  24.  
    System. out.println(bean);
  25.  
    }
  26.  
    }
  27.  
    }


運行Application:
控制台掃描到了/hello,即映射成功

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°
把Application注釋掉運行ComponentTest:

å¨è¿éæå¥å¾çæè¿°
參考:
https://blog.csdn.net/Lamb_IT/article/details/80918704
https://jingyan.baidu.com/article/7908e85cc6930daf481ad2b6.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM