java - Error with private field using @Autowired
问题描述
I've an error using Spring when changing the visibility of a variable.
I've this code (which works fine)
@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
is an interface, and I've a class HappyFortunateService
which implements it, and I've it annotated with @Component
as well)
with this main method
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();
}
And when I turn on the TennisCoach
class the fortunateService
variable visibility to private
, I get this error:
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$0(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
Does anybody know why? Spring version: 5.2.9 Java SE15
EDIT: My project is set up adding the Spring JAR files to the ModulePath, I'm not using Maven.
My module-info.java looks like this:
module spring_project {
requires spring.context;
requires java.logging;
requires spring.beans;
exports me.davichete.springproject;
}
EDIT: I tested it deleting the module-info.java, and now it seems to work, probably related to the answer of @Menelaos
解决方案
Try adding a constructor and making your field final
If you are using Lambok
, you could do the following:
- Set
@RequiredArgsConstructor
on your class - which will generate a constructor with params for all final variables. - Change your field to final, and get rid of @Autowired.
Spring will take care of injecting the value for final fields.
If you are not using lambok, you need to add the constructor by hand.
See the constructor injection example @ https://stackoverflow.com/a/55473346/1688441
Java 9 Modules
Have a look also at the following: How to solve InaccessibleObjectException ("Unable to make {member} accessible: module {A} does not 'opens {package}' to {B}") on Java 9?
Your error is due to limitations and changes in Java 9.
推荐阅读
- azure - 如何使用 jar 在 azure 管道中部署功能?
- python - TypeError:对象字典不能在“等待”表达式中使用
- node.js - Cassandra 的 Node.js 驱动程序为不同的 fetchSize 返回不正确的结果集
- git - 了解范围差异的输出
- http - VPN 断开后无法在 Raspbian 上通过 SSH/HTTP 连接
- javascript - 如何在原生 JavaScript 中进行浏览器自动化?
- informatica - 特殊字符的映射参数
- ethereum - 使用 truffle 部署智能合约时出错
- haskell - Haskell - 为什么我不在范围内:数据构造函数“ZipList”错误
- python - 如果用户在不提供任何值的情况下按 ENTER,程序将自动将 μ 设置为 0,将 σ2 设置为 1