更改自动装配的 bean 类型意外更改值?

Changing Autowired bean type unexpectedly changes value?

我尝试创建一个应用程序并 运行 进入一些奇怪的行为。首先,我将 运行 完成我的设置。这是我的配置 class:

ProblemApp.java

@SpringBootApplication
public class ProblemApp
{
    public static void main(String[] args)
    {
        var context = SpringApplication.run(ProblemApp.class);
        var tblController = context.getBean(TableController.class);
        tblController.printTable();
    }
    @Bean
    public TableController getTableController()
    {
        return new TableController();
    }
    @Bean("componentTable")
    public String[] getComponentTable() //weird
    {
        return new String[] { "application.components" };
    }
}

这是我的组件:

TableController.java

@Controller
public class TableController
{
    private static final Logger log = LoggerFactory.getLogger(TableController.class);

    @Autowired
    private String[] componentTable; //weird

    public void printTable()
    {
        log.info("Component table: " + Arrays.deepToString(componentTable));
    }
}

这是我的 module-info.java 和目录结构:

module problem.application
{
    exports application;
    exports controller;

    opens controller to spring.core;
    opens application to spring.core;

    requires spring.context;
    requires spring.boot;
    requires spring.boot.autoconfigure;
    requires spring.beans;
    requires spring.core;
    requires java.sql;
    requires org.slf4j;
}
src/main/java/
    application
        ProblemApp.java
    controller
        TableController.java
    module-info.java
src/test/java/ is empty
src/main/resources/ is empty

这是我用来检索依赖项的 pom.xml(在 Spring Tool Suite 4 中使用 Maven):

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>problem.application</groupId>
    <artifactId>problem-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Problematic application</name>
    <description>An application with some problems</description>

    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <release>12</release>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

</project>

这段代码按我预期的那样工作。输出的相关部分是:

2019-09-11 10:55:21.351  INFO 21060 --- [           main] controller.TableController               : 
Component table: [application.components]

现在,我尝试将 Bean componentTable 的类型更改为 Object[]。在 ProblemApp 中:

@Bean("componentTable")
public Object[] getComponentTable() //weird
{
    return new Object[] { "application.components" };
}

在表控制器中:

@Autowired
private Object[] componentTable; //weird

突然,程序的输出发生了翻天覆地的变化:

2019-09-11 10:57:05.630  INFO 10156 --- [           main] controller.TableController               : 
Component table: [org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor@b40bb6e, 
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@3f28bd56, 
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@3276732, 
org.springframework.context.annotation.ConfigurationClassPostProcessor@f74e835, 
org.springframework.context.support.PropertySourcesPlaceholderConfigurer@48c35007, 
org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar@4b3c354a, 
org.springframework.context.event.EventListenerMethodProcessor@31e3250d, 
org.springframework.context.event.DefaultEventListenerFactory@19fe4644, 
application.ProblemApp$$EnhancerBySpringCGLIB$e1f363f@21d8bcbe,
...
// more Spring-looking things and then environment information

这是怎么回事?

当自动写入数组或类型 T 的列表时,它会首先尝试将类型为 T 的所有 bean 注入其中。所以对于 :

@Autowired
private String[] componentTable; 

它将首先尝试注入所有类型为 String 的bean。然而,由于没有这样的 beans,它会尝试注入一个类型为 String[] 的 bean。当您将 componentTable bean 定义为 String[] 时,它将被注入。

遵循相同的逻辑:

@Autowired
private Object[] componentTable;

它将首先尝试注入所有类型为Object的bean。因为每个 bean 都必须是 Object 类型。这意味着将注入所有 spring 个 bean。因此它打印出所有 spring bean 信息。