更改自动装配的 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 信息。
我尝试创建一个应用程序并 运行 进入一些奇怪的行为。首先,我将 运行 完成我的设置。这是我的配置 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 信息。