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