当前位置 : 主页 > 编程语言 > java >

Spring component-scan XML配置与@ComponentScan注解配置

来源:互联网 收集:自由互联 发布时间:2023-01-30
目录 前言 准备 @Component的bean XML配置 Java配置 配置 @Configuration的bean XML配置 配置 Java配置 配置 小结 总结 关于SpringBoot 前言 无论Spring的XML配置或者Java配置,都可以配置自动扫描,也就是
目录
  • 前言
  • 准备
  • @Component的bean
    • XML配置
    • Java配置 配置
  • @Configuration的bean
    • XML配置 配置
    • Java配置 配置
    • 小结
  • 总结
    • 关于SpringBoot

      前言

      无论Spring的XML配置或者Java配置,都可以配置自动扫描,也就是在指定包及其子包下的component,都会被自动扫描并被Spring容器管理。

      注:component指的是被 @Component 注解及其变种(如 @Controller@Service@Repository@Configuration 等)所修饰的类。

      环境:

      • Ubuntu 22.04
      • IntelliJ IDEA 2022.1.3
      • JDK 17.0.3
      • Spring 5.3.21

      准备

      创建Maven项目 test0831

      修改 pom.xml 文件,添加依赖:

              ......
              <!-- https://mvnrepository.com/artifact/junit/junit -->
              <dependency>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>4.13.2</version>
                  <scope>test</scope>
              </dependency>
      
              <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-webmvc</artifactId>
                  <version>5.3.21</version>
              </dependency>
              ......

      src/test/java 目录下创建测试:

      public class MyTest {}

      创建如下POJO:

      • Axe :Axe接口;
      • StoneAxe :Axe实现类;
      • SteelAxe :Axe实现类;
      • Person :Person持有Axe
      package pojo;
      
      public interface Axe {
          public void chop();
      }
      package pojo;
      import org.springframework.stereotype.Component;
      @Component
      public class StoneAxe implements Axe{
          @Override
          public void chop() {
              System.out.println("Stone axe!");
          }
      }
      package pojo;
      import org.springframework.context.annotation.Primary;
      import org.springframework.stereotype.Component;
      @Component
      @Primary
      public class SteelAxe implements Axe{
          @Override
          public void chop() {
              System.out.println("Steel axe!");
          }
      }
      
      package pojo;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.stereotype.Component;
      @Component
      public class Person {
          private String name;
          private Axe axe;
      
          public void setAxe(Axe axe) {
              this.axe = axe;
          }
          public void setName(String name) {
              this.name = name;
          }
      
          public void useAxe() {
              System.out.println("I am " + name);
              axe.chop();
          }
          @Autowired
          public Person(@Value("Tom") String name, Axe axe) {
              this.name = name;
              this.axe = axe;
          }
      }

      注:本例使用了 @Autowired 注解来自动装配注入,默认是 byType ,当有多个类都满足条件时Spring会报错,所以使用了 @Primary 注解来指定优先选择该类。

      @Component的bean

      XML配置

      配置:

      src/main/resources 目录下创建 applicationContext.xml 文件:

      <?xml version="1.0" encoding="utf-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd">
      
         <context:component-scan base-package="pojo"/>
      
      </beans>

      测试:

      创建测试如下:

          @Test
          public void test1() {
              var ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
              var person = ctx.getBean("person", Person.class);
              person.useAxe();
          }

      运行测试,结果如下:

      I am Tom
      Steel axe!

      Java配置 配置

      创建Java配置类 MyConfig.java 如下:

      package config;
      
      import org.springframework.context.annotation.ComponentScan;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      @ComponentScan(basePackages = {"pojo"})
      public class MyConfig {
      
      }

      测试:

      创建测试如下:

          @Test
          public void test2() {
              var ctx = new AnnotationConfigApplicationContext(MyConfig.class);
      
              var person = ctx.getBean("person", Person.class);
      
              person.useAxe();
          }

      运行测试,结果如下:

      I am Tom
      Steel axe!

      @Configuration的bean

      自动扫描时,如果遇到Java配置类,也会加载其配置。

      pojo 包下添加Java配置类 MyConfig2

      package pojo;
      
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      public class MyConfig2 {
          @Bean
          public String xxx() {
              return "xxx";
          }
      }

      本例中, MyConfig2 是一个配置类,其中配置了ID为 xxx 的bean。

      XML配置 配置

      前面已经配置了:

         <context:component-scan base-package="pojo"/>

      MyConfig2pojo 包下,所以无需额外的配置。

      测试

      创建测试如下:

          @Test
          public void test3() {
              var ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
      
              var xxx = ctx.getBean("xxx", String.class);
      
              System.out.println(xxx);
          }

      运行测试,结果如下:

      xxx

      Java配置 配置

      前面已经配置了:

      @ComponentScan(basePackages = {"pojo"})

      MyConfig2pojo 包下,所以无需额外的配置。

      测试

      创建测试如下:

          @Test
          public void test4() {
              var ctx = new AnnotationConfigApplicationContext(MyConfig.class);
      
              var xxx = ctx.getBean("xxx", String.class);
      
              System.out.println(xxx);
          }

      运行测试,结果如下:

      xxx

      小结

      @Configuration@Component 的变种,因此也会被自动扫描并加载。

      如果Java配置类不是在自动扫描的路径里,则需要显式加载:

      通过XML配置加载:

         <context:annotation-config/>
      
         <bean class="config.MyConfig3"/>

      通过Java配置加载:

      @Import({MyConfig3.class})

      总结

      • 在类上添加 @Component (或者其变种)注解。
      • 配置自动扫描,以下两种方式都可以:

      XML配置:

         <context:component-scan base-package="pojo"/>

      Java配置:

      @Configuration
      @ComponentScan(basePackages = {"pojo"})
      public class MyConfig {
      
      }

      对于自动扫描路径里面的Java配置类( @Configuration 注解所修饰的类),也会被加载生效。

      注:关于Spring的XML配置和Java配置,详见我另一篇文档 https://blog.csdn.net/duke_ding2/article/details/125605817

      关于SpringBoot

      SpringBoot的入口程序一般如下:

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

      即,调用 SpringApplication.run() 方法来启动程序,第一个参数是一个类,该类需要被 @SpringBootApplication 注解所修饰。

      @SpringBootApplication 该注解包含了以下3个注解:

      • @SpringBootConfiguration
      • @EnableAutoConfiguration
      • @ComponentScan

      也就是说, @SpringBootApplication 包含了上面提到的Java配置的两个注解 @Configuration
      @ComponentScan

      换句话说, @SpringBootApplication 所修饰的类就是程序的主配置类。

      有一点需要注意的是,在默认情况下(没有指定包扫描路径),会自动扫描主配置类所在的包(及其子包)。因此,该包及子包下的组件类和配置类都会被扫描。

      当然也可以显式指定包扫描路径,需要注意的是,其属性名是 scanBasePakcages ,而不是 basePackages

      对比下面两个注解:

      • @ComponentScan(basePackages = "com.example.demo.pojo")
      • @SpringBootApplication(scanBasePackages = "com.example.demo.pojo")

      若显式指定了包扫描路径,则会覆盖默认设置(主配置类所在的包及子包不会被扫描)。

      到此这篇关于Spring component-scan XML配置与@ComponentScan注解配置的文章就介绍到这了,更多相关Spring XML配置内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

      上一篇:SpringBoot利用注解来实现Redis分布式锁
      下一篇:没有了
      网友评论