loader ' 应用程序 ' attempted duplicate class definition"将类标记为 @Transactional 后-6ren"> loader ' 应用程序 ' attempted duplicate class definition"将类标记为 @Transactional 后-将类(class)标记为 @Transactional 后(见下文),当我的应用程序在用户仍然登录的情况下重新加载时,我收到关于“尝试重复的类定义”的 LinkageErrors。 错误: org.s-6ren">
gpt4 book ai didi

spring - "LinkageError--> loader ' 应用程序 ' attempted duplicate class definition"将类标记为 @Transactional 后

转载 作者:行者123 更新时间:2023-12-01 05:50:27 24 4
gpt4 key购买 nike

将类(class)标记为 @Transactional 后(见下文),当我的应用程序在用户仍然登录的情况下重新加载时,我收到关于“尝试重复的类定义”的 LinkageErrors。

错误:

org.springframework.security.authentication.InternalAuthenticationServiceException: java.lang.LinkageError-->loader 'app' (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) attempted duplicate class definition for [redacted].AdminUserDao$$FastClassBySpringCGLIB$$2ffa020e.
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:126)

其中 adminUserDao 是我们在自定义 UserDetailsS​​ervice 中用于在身份验证期间加载用户的 dao。

原AdminUserDao.java
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class AdminUserDao {
private final SessionFactory sessionFactory;

@Autowired
public AdminUserDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

public AdminUser getUserByEmailAddress(String emailAddress) {
String hql = "from " + AdminUser.class.getName()
+ " admin_user where admin_user.emailAddress = :emailAddress";
Session session = null;
try {
session = sessionFactory.openSession();
return session
.createQuery(hql, AdminUser.class)
.setParameter("emailAddress", emailAddress)
.uniqueResult();
} finally {
if (session != null && session.isOpen()) {
session.close();
}
}
}

事务 AdminUserDao.java
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@Repository
public class AdminUserDao {
private final SessionFactory sessionFactory;

@Autowired
public AdminUserDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

public AdminUser getUserByEmailAddress(String emailAddress) {
String hql = "from " + AdminUser.class.getName()
+ " admin_user where admin_user.emailAddress = :emailAddress";
return sessionFactory.getCurrentSession()
.createQuery(hql, AdminUser.class)
.setParameter("emailAddress", emailAddress)
.uniqueResult();
}
}

事务管理器 Bean
@Bean
public HibernateTransactionManager transactionManager(@Qualifier("sessionFactory") SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}

重现步骤:
  • 登录
  • 重新启动应用程序(无需注销)
  • 重新加载页面(用户仍应登录)
  • 登出
  • 尝试使用同一用户再次登录。当 Spring 尝试对用户进行身份验证时会触发该错误。

  • 我看到 Stack Overflow 上的其他人在错误地定义了自定义 ClassLoader ( here) 时遇到了这个问题;但是,我没有使用自定义 ClassLoader。

    潜在相关的依赖版本:
  • java :11
  • Spring Boot:2.1.1.RELEASE
  • Spring :5.1.3.RELEASE
  • Spring Security:5.1.4.RELEASE
  • 最佳答案

    上面给出的链接:https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch08s06.html
    https://stackoverflow.com/users/1567452/jwilner
    给出正确的提示 (thx ;) )

    @Transactional 注释意味着 Spring 正在为您生成一个代理类,该类使用以下内容包装您的方法:

    GeneratedProxy {

    void proxiedMethod(){
    try{
    tx.begin();

    yourClass.yourMethod();

    tx.commit();
    }
    .. plus usual rollback and error stuff ..
    }
    }

    现在 spring 有两个选项(见 https://botproxy.net/docs/how-to/mismatched-proxy-types-jdk-vs-cglib-when-using-enablecaching-with-custom-aop-advice/ ):

    如果您的代码实现了一个接口(interface),他将使用 JDK 代理并公开该接口(interface)的所有方法:

    (参见例如 https://www.byteslounge.com/tutorials/jdk-dynamic-proxies JDK 代理示例)

    如果您的代码没有实现任何接口(interface),他将创建一个 CGLIB 代理
    (并且基本上猜测要公开哪些方法)

    最后,在他生成 CGLIB 代理的情况下,他将创建一个运行时类,例如
    AuthcUserService$$EnhancerBySpringCGLIB$$5c9dcb68

    一个 JDK 代理,他将创建一个类似 com.sun.proxy.$Proxy1631 的类

    这两个将在 setter(生成的 setter)方法中被强制转换为正确的类:

    在第一种情况下,您可以在父类中使用类本身
    在第二种情况下,您将使用该界面,否则您会得到
    org.springframework.beans.factory.BeanNotOfRequiredTypeException

    在您的情况下,您也许可以摆脱@Transactional,
    就我而言,我无法摆脱@Transactional,因为我正在跨多个数据库进行真正的交易。

    总而言之,这发生在 java 13 中,可能是由于 jee 和反射的变化,实际上在 jdk1.8 中,下面的代码完全不知道这些机制。

    关于spring - "LinkageError--> loader ' 应用程序 ' attempted duplicate class definition"将类标记为 @Transactional 后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54894041/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com