是什么导致Spring使用AnnotationConfigApplicationContext时无法加载配置类?

发布于 2025-01-10 16:42:40 字数 7856 浏览 0 评论 0原文

我最近遇到了这个问题,在搜索 stackoverflow 网站后,找不到可行的解决方案。我收到的错误是 Spring 在加载配置类时遇到问题。我使用注释和 Spring 类来配置(而不是 XML 文件),以练习使用注释而不是 XML 文件配置 Java 应用程序。

我已经仔细检查以确保所需的注释存在,并且 Spring 配置文件标记有 @Configuration 并且配置文件中的所有 bean 都标记有 @Bean >。此外,特定的 Bean 还标有 @Component

创建测试类后,Spring 似乎仍然无法找到配置文件。我仔细检查了 pom 文件,看看是否缺少任何依赖项,但据我所知,似乎需要的依赖项就在那里。我不确定我还缺少什么,也不知道为什么 Spring 找不到配置文件。任何帮助将不胜感激。

这是我的 pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.spring</groupId>
  <artifactId>Spring_JavaConfig</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>Spring_JavaConfig</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <springframework.version>4.3.6.RELEASE</springframework.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springframework.version}</version>
    </dependency>
  </dependencies>
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.2</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

这是我的 Java 文件:

Dao 类(没有真正访问数据库,只是练习使用 Spring 注释而不是 XML 文件进行配置):

package com.spring;

import org.springframework.stereotype.Component;

@Component
public class Dao {
  public void create() {
    System.out.println("Created");
  }
}

Spring Config 类:< /strong>

package com.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
  @Bean
  public Dao dao() {
    return new Dao();
  }
}

测试类:

package com.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    Dao dao = context.getBean(Dao.class);
    dao.create();
    context.close();
  }
}

这是我收到的错误:

Feb 28, 2022 1:39:12 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@39c0f4a: startup date [Mon Feb 28 13:39:12 EST 2022]; root of context hierarchy
Exception in thread "main" java.lang.IllegalStateException: Cannot load configuration class: com.spring.SpringConfig
at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:403)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:249)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:281)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:125)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at com.spring.Test.main(Test.java:9)
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.context.annotation.ConfigurationClassEnhancer.newEnhancer(ConfigurationClassEnhancer.java:119)
at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:107)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:393)
... 7 more
Caused by: java.lang.IllegalStateException: Unable to load cache item
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:79)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.springframework.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:174)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:153)
at org.springframework.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)
... 10 more
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
... 17 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @2f8f5f62
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at org.springframework.cglib.core.ReflectUtils$1.run(ReflectUtils.java:54)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at org.springframework.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:44)
... 25 more

I've run across this issue recently and after searching the stackoverflow site, couldn't find a working solution. The error I'm getting is that Spring is having issue loading the configuration class. I'm using annotations and a Spring class to configure, instead of an XML file, to practice configuring Java apps with annotations instead of an XML file.

I've double checked to make sure the needed annotations were there and that the Spring config file was marked with @Configuration and all of the beans inside the config file marked with @Bean. Also, the particular beans were marked with @Component.

After creating a test class, it seems Spring is still having trouble finding the config file. I doubled checked the pom file to see if I was missing any dependencies but as far as I know, it seems the needed dependencies are there. I'm not sure what else I'm missing or why Spring is having trouble finding the config file. Any help would be greatly appreciated.

Here is my pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.spring</groupId>
  <artifactId>Spring_JavaConfig</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>Spring_JavaConfig</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <springframework.version>4.3.6.RELEASE</springframework.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springframework.version}</version>
    </dependency>
  </dependencies>
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.2</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

And here are my Java files:

Dao class (not really accessing database, just practicing configuring with Spring Annotations instead of XML file):

package com.spring;

import org.springframework.stereotype.Component;

@Component
public class Dao {
  public void create() {
    System.out.println("Created");
  }
}

Spring Config class:

package com.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
  @Bean
  public Dao dao() {
    return new Dao();
  }
}

Test class:

package com.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    Dao dao = context.getBean(Dao.class);
    dao.create();
    context.close();
  }
}

Here is the error I'm getting:

Feb 28, 2022 1:39:12 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@39c0f4a: startup date [Mon Feb 28 13:39:12 EST 2022]; root of context hierarchy
Exception in thread "main" java.lang.IllegalStateException: Cannot load configuration class: com.spring.SpringConfig
at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:403)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:249)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:281)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:125)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at com.spring.Test.main(Test.java:9)
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.context.annotation.ConfigurationClassEnhancer.newEnhancer(ConfigurationClassEnhancer.java:119)
at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:107)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:393)
... 7 more
Caused by: java.lang.IllegalStateException: Unable to load cache item
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:79)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.springframework.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:174)
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:153)
at org.springframework.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)
... 10 more
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
... 17 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @2f8f5f62
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at org.springframework.cglib.core.ReflectUtils$1.run(ReflectUtils.java:54)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at org.springframework.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:44)
... 25 more

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

何必那么矫情 2025-01-17 16:42:40

前言

这个问题实际上与我在这里一般性回答的问题非常相似,其中我还描述了--add-opens 解决方法@victoraugustofd在他的回答中提到。

但是因为另一个答案不包含 MCVE 而这个答案包含,所以这个问题实际上更好地回答,不仅是通用的,而且是以更具体的方式,因为将来的每个读者都可以看到代码和 POM,以便重现问题和解决方案。这就是我们希望在 Stack Overflow 上提出的问题。

Preface

This question is actually quite similar to the one I answered generically here, where among other things I also described the --add-opens workaround @victoraugustofd mentioned in his answer here.

But because the other answer does not contain an MCVE and this one does, this question is actually better to answer not just in a generic but in a more concrete way, because every reader in the future can see code and a POM in order to reproduce both the problem and the solution. This is the kind of question we want here on Stack Overflow. ????

Problem root cause

Like I said in the other answer, the problem is that JEP 396 is limiting access to internal JDK classes since JDK 16.

Solution

So if you want to avoid the workaround of opening up packages, just upgrade to a more recent Spring version embedding a more recent CGLIB version. For 4.3.x, there is no such update, neither is there for 5.0.x. But if you e.g. can upgrade to 5.1.20, 5.2.19 or 5.3.16, your example application works on JDK 16+. There might be slightly older minor-minor releases containing suitable CGLIB versions, but why bother if you upgrade anyway? Just use the latest minor-minor for 5.1, 5.2 or 5.3.

花开半夏魅人心 2025-01-17 16:42:40

从 Java 9 开始,Java 引入了 Module 以及 Spring 等一些框架,依赖在一些反射行为上,并且由于模块化,某些类的属性无法通过反射访问。
解决方案是改变这些属性的可访问性,但这需要很长时间。

真正的解决方案是在运行应用程序时添加此 VM 选项: --add-opens java.base/java.lang=ALL-UNNAMED

请参阅另一篇具有类似问题的帖子上的这个很好的答案:
类似问题的答案

我将您的应用程序更改为使用Spring Boot,您考虑过使用它吗?
对于 Spring 应用程序来说,它是一个非常方便的解决方案,因为它抽象了许多配置。这是包含详细示例的链接: Spring Boot 示例

Since Java 9, Java introduced Modules and some frameworks such as Spring, rely on several Reflection behaviour and because of the modularization, some classes had their attribute not accessible through Reflection.
The solution would be change the accessibility of these attributes, but it would take forever to do that.

The real solution is to add this VM option when you run your application: --add-opens java.base/java.lang=ALL-UNNAMED

Please refer to this great answer on another post with a similar problem:
Answer to similar question

I changed your application to use Spring Boot, have you consider using it?
For Spring applications, it is a very handy solution since it abstract many configurations. Here is a link with a detailed example: Spring Boot Example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文