使用@Autowired 的私有字段出错
Error with private field using @Autowired
我在使用 Spring 更改变量的可见性时出错。
我有这段代码(工作正常)
@Component
public class TennisCoach implements Coach {
@Autowired
public FortuneService fortuneService;
@Override
public String getDailyWorkout() {
return "Do tennis stuff!";
}
@Override
public String getFortune() {
return fortuneService.getFortune();
}
}
(FortunateService
是一个接口,我有一个 class HappyFortunateService
来实现它,我也用 @Component
注释了它)
用这个主要方法
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Coach annotatedCoach = context.getBean("tennisCoach", Coach.class);
System.out.println(annotatedCoach.getDailyWorkout());
System.out.println(annotatedCoach.getFortune());
context.close();
}
当我打开 TennisCoach
class fortunateService
变量对 private
的可见性时,我收到此错误:
org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tennisCoach': Injection of autowired dependencies failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private me.davichete.springproject.FortuneService me.davichete.springproject.TennisCoach.fortuneService accessible: module spring_project does not "opens me.davichete.springproject" to module spring.core
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tennisCoach': Injection of autowired dependencies failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private me.davichete.springproject.FortuneService me.davichete.springproject.TennisCoach.fortuneService accessible: module spring_project does not "opens me.davichete.springproject" to module spring.core
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=12=](AbstractBeanFactory.java:324)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:85)
at spring_project/me.davichete.springproject.HelloSpringApp.main(HelloSpringApp.java:8)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private me.davichete.springproject.FortuneService me.davichete.springproject.TennisCoach.fortuneService accessible: module spring_project does not "opens me.davichete.springproject" to module spring.core
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:361)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:301)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:177)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:171)
at spring.core@5.2.9.RELEASE/org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:782)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:667)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
... 13 more
有人知道为什么吗?
Spring版本:5.2.9
JavaSE15
编辑:我的项目设置为将 Spring JAR 文件添加到 ModulePath,我没有使用 Maven。
我的模块-info.java 看起来像这样:
module spring_project {
requires spring.context;
requires java.logging;
requires spring.beans;
exports me.davichete.springproject;
}
编辑:我测试了删除模块-info.java,现在它似乎可以工作了,可能与@Menelaos
的回答有关
尝试添加构造函数并使您的字段成为最终字段
如果您使用的是 Lambok
,您可以执行以下操作:
- 在您的 class 上设置
@RequiredArgsConstructor
- 这将为所有最终变量生成一个带有参数的构造函数。
- 将您的字段更改为最终字段,并删除@Autowired。
Spring 将负责为最终字段注入值。
如果没有使用lambok,需要手动添加构造函数
查看构造函数注入示例@
Java 9 个模块
另请查看以下内容:
您的错误是由于 Java 9.
中的限制和更改造成的
我在使用 Spring 更改变量的可见性时出错。
我有这段代码(工作正常)
@Component
public class TennisCoach implements Coach {
@Autowired
public FortuneService fortuneService;
@Override
public String getDailyWorkout() {
return "Do tennis stuff!";
}
@Override
public String getFortune() {
return fortuneService.getFortune();
}
}
(FortunateService
是一个接口,我有一个 class HappyFortunateService
来实现它,我也用 @Component
注释了它)
用这个主要方法
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Coach annotatedCoach = context.getBean("tennisCoach", Coach.class);
System.out.println(annotatedCoach.getDailyWorkout());
System.out.println(annotatedCoach.getFortune());
context.close();
}
当我打开 TennisCoach
class fortunateService
变量对 private
的可见性时,我收到此错误:
org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tennisCoach': Injection of autowired dependencies failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private me.davichete.springproject.FortuneService me.davichete.springproject.TennisCoach.fortuneService accessible: module spring_project does not "opens me.davichete.springproject" to module spring.core
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tennisCoach': Injection of autowired dependencies failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private me.davichete.springproject.FortuneService me.davichete.springproject.TennisCoach.fortuneService accessible: module spring_project does not "opens me.davichete.springproject" to module spring.core
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=12=](AbstractBeanFactory.java:324)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144)
at spring.context@5.2.9.RELEASE/org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:85)
at spring_project/me.davichete.springproject.HelloSpringApp.main(HelloSpringApp.java:8)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private me.davichete.springproject.FortuneService me.davichete.springproject.TennisCoach.fortuneService accessible: module spring_project does not "opens me.davichete.springproject" to module spring.core
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:361)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:301)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:177)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:171)
at spring.core@5.2.9.RELEASE/org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:782)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:667)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
at spring.beans@5.2.9.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
... 13 more
有人知道为什么吗? Spring版本:5.2.9 JavaSE15
编辑:我的项目设置为将 Spring JAR 文件添加到 ModulePath,我没有使用 Maven。
我的模块-info.java 看起来像这样:
module spring_project {
requires spring.context;
requires java.logging;
requires spring.beans;
exports me.davichete.springproject;
}
编辑:我测试了删除模块-info.java,现在它似乎可以工作了,可能与@Menelaos
的回答有关尝试添加构造函数并使您的字段成为最终字段
如果您使用的是 Lambok
,您可以执行以下操作:
- 在您的 class 上设置
@RequiredArgsConstructor
- 这将为所有最终变量生成一个带有参数的构造函数。 - 将您的字段更改为最终字段,并删除@Autowired。
Spring 将负责为最终字段注入值。
如果没有使用lambok,需要手动添加构造函数
查看构造函数注入示例@
Java 9 个模块
另请查看以下内容:
您的错误是由于 Java 9.
中的限制和更改造成的