Changing Autowired bean type unexpectedly changes value?

*爱你&永不变心* 提交于 2020-01-16 00:43:35

问题


I've tried to create an Application and ran into some funky behavior. First, I'll run through my setup. Here's my configuration 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" };
    }
}

Here's my component:

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));
    }
}

This is my module-info.java and directory structure:

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

This is the pom.xml I use to retrieve dependencies (using Maven in Spring Tool Suite 4):

<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>

This code, as it is, works as I expected it to. The relevant part of the output is:

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

Now, I tried to change the type of Bean componentTable to Object[]. In ProblemApp:

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

In TableController:

@Autowired
private Object[] componentTable; //weird

Suddenly, the output of the program changes drastically:

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$$7e1f363f@21d8bcbe,
...
// more Spring-looking things and then environment information

What is going on here?


回答1:


When auto-wring on an array or a list of type T , it will first try to inject all beans which the type is T into it. So for :

@Autowired
private String[] componentTable; 

It will first try to inject all beans which the type is String . However since there are no such beans, it will then try to inject a bean which the type is String[] . As you define componentTable bean as String[] , it will be injected.

Follow the same logic on :

@Autowired
private Object[] componentTable;

It will first try to inject all beans which the type is Object. As every bean must be an Object type . It means all spring beans will be injected. Hence it prints out all the spring bean information.



来源:https://stackoverflow.com/questions/57893233/changing-autowired-bean-type-unexpectedly-changes-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!