zoukankan      html  css  js  c++  java
  • Spring和SpringBoot中的@Component 和@ComponentScan注解用法介绍和注意事项

    过本文你将学到:

    • Component Scan是什么?
    • 为什么ComponentScan很重要?
    • 项目中Spring Boot会对哪些包自动执行扫描(Component Scan)?
    • 如何利用Spring Boot定义扫描范围?
    • 项目启动时关于Component Scan的常见报错

    @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应用)中如何定义Component Scan

    Spring Boot项目
    总结:

    1. 如果你的其他包都在使用了@SpringBootApplication注解的main
      app所在的包及其下级包,则你什么都不用做,SpringBoot会自动帮你把其他包都扫描了
    2. 如果你有一些bean所在的包,不在main
      app的包及其下级包,那么你需要手动加上@ComponentScan注解并指定那个bean所在的包

    举个例子,看下面定义的类

    package com.demo.springboot;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class SpringbootApplication {
    
        public static void main(String[] args) {
            ApplicationContext applicationContext = 
                    SpringApplication.run(SpringbootApplication .class, args);
    
            for (String name : applicationContext.getBeanDefinitionNames()) {
                System.out.println(name);
            }
        }
    }

    类 SpringbootApplication 在com.demo.springboot包下,这个类使用了@SpringBootApplication注解,该注解定义了Spring将自动扫描包com.demo.springboot及其子包下的bean

    如果你项目中所有的类都定义在com.demo.springboot包及其子包下,那你不需要做任何事

    但假如你一个类定义在包com.demo.somethingelse下,则你需要将这个新包也纳入扫描的范围,有两个方案可以达到这个目的。

    方案1
    定义@CoponentScan(“com.demo”)

    这么做扫描的范围扩大到整个父包com.demo

    @ComponentScan(“com.demo”)
    @SpringBootApplication
    public class SpringbootApplication {

    方案2
    定义分别扫描两个包
    @ComponentScan({“com.demo.springboot”,”com.demo.somethingelse”})

    @ComponentScan({"com.demo.springboot","com.demo.somethingelse"})
    @SpringBootApplication
    public class SpringbootApplication {

    特别注意一下:如果使用了方案2,如果仅仅只写@ComponentScan({"com.demo.somethingelse"})将导致com.demo.springboot包下的类无法被扫描到(框架原始的默认扫描效果无效了)

    Spring Boot项目
    在非Spring Boot项目中,我们必须显式地使用@ComponentScan注解定义被扫描的包,可以通过XML文件在应用上下文中定义或在Java代码中对应用上下文定义

    Java代码方式

    @ComponentScan({"com.demo.package1","com.demo.package2"})
    @Configuration
    public class SpringConfiguration {

    XML文件方式

    <context:component-scan base-package="com.demo.package1, com.demo.package2"/>

    项目中常见关于Component Scan的报错
    你是否在项目启动中遇到过类似这样的报错:

    WARNING: No mapping found for HTTP request with URI [/spring-mvc/login] in DispatcherServlet with name ‘dispatcher’

    WARNING: No mapping found for HTTP request with URI [/list-todos] in DispatcherServlet with name ‘dispatcher’

    或者:

    ERROR:No qualifying bean of type [com.demo.springboot.jpa.UserRepository] found for dependency [com.demo.springboot.jpa.UserRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}…

    报错的根因都是bean没有被Spring找到
    遇到这些错误你应该检查:

    你是否给类加了正确的注解@Controller@Repository@Service@Component
    你是否在应用上下文定义了Component Scan
    报错类所在的包是否在Component Scan中指定的包的范围
    @Component 和@ComponentScan 的区别
    @Component 和 @ComponentScan的使用目的不一样

    在某个类上使用@Component注解,表明当需要创建类时,这个被注解的类是一个候选类。就像是举手。
    @ComponentScan用于扫描指定包下的类。就像看都有哪些举手了。

  • 相关阅读:
    Paragon NTFS for Mac免费获取官方赠送正版.更新获取ntfs for mac 14方法
    Python修饰器的函数式编程
    Python装饰器与面向切面编程
    linux配置IP的方法
    Centos搭建SVN服务器三步曲
    [CentOS 6.5 X64]讓firefox java plugin 啟動
    逻辑分析题(三)
    逻辑分析题汇总(一)
    第十章—DOM(0)—NODE类型
    第十章—DOM(三)——Text类型
  • 原文地址:https://www.cnblogs.com/wangcp-2014/p/13604653.html
Copyright © 2011-2022 走看看