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

这篇文章主要介绍了Spring component-scan XML配置与@ComponentScan注解配置,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

前言

无论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配置内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!

本文标题为:Spring component-scan XML配置与@ComponentScan注解配置

基础教程推荐