org.springframework.beans.BeanUtils.copyProperties(对象源,对象目标)抛出错误无法将属性“通道”从源复制到目标

问题描述 投票:0回答:1

这是源类:

@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@JsonSerialize(as = RequestContext.class)
public class RequestContext implements Serializable {

    private static final long serialVersionUID = 1L;

    private String statusCode;

    private String statusType;
    
    private String txnId;
    
    private int channelId;

    private String channel;

}

这些是目标类及其父类:

@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@JsonSerialize(as = Transaction.class)
public class Transaction extends TransactionBase implements Serializable {

    private static final long serialVersionUID = 1L;

    private Actors actors = Actors.SENDER;
    private PartnerMaster senderPartner;
    private PartnerMaster receiverPartner;
    private PartnerMaster userPartner;
    private UserMaster senderUser;
    private UserMaster receiverUser;

    private WalletAction adjustmentType;
    private BigDecimal netAmount = BigDecimal.ZERO;
    private BigDecimal amount = BigDecimal.ZERO;
    private BigDecimal rollbackAmount = BigDecimal.ZERO;

    private Charges charges = new Charges();

    private List<SystemWalletMaster> systemWallets = new ArrayList<>();
    private List<SystemCdrBean> systemCdr = new ArrayList<>();

    private List<Items> products;

    /** generic params for dynamic values. **/
    private HashMap<String, Object> genericParams = new HashMap<>();

}
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
public class TransactionBase extends TransactionFlags implements Serializable {

    private static final long serialVersionUID = 1L;

    private int channelId;
    private String channel;
    private String mvnoId;

    private ServiceMaster service = new ServiceMaster();

    private String featureId;

    private String statusCode;
    private String statusCodeReceiver;
    private String statusType;
    private String txnType;
    private String message;

    private String txnId;
    private String requestId;
    private long duration;

    private TransactionCommon transactionCommon;

}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TransactionFlags implements Serializable {

    private static final long serialVersionUID = 1L;

    /** flags . **/
    private boolean rollback;
    
    
    private boolean adjustment;
    private boolean adjustmentSystem;
    private boolean isWhitelisted;
    private boolean adjustCommission;
    private boolean adjustFee;
    private boolean adjustSystemCommission;
    private boolean adjustSystemFee;
    private boolean isLimitExists;
    private boolean isLimitAllServices;
    private boolean isApprovalEnabled;

}

豆子复制:

@Component
@Slf4j
public class RequestInterceptor implements HandlerInterceptor {

    @Autowired
    private Transaction transaction;

    @Autowired
    private RequestContext requestContext;

    @Autowired
    private UserContext userContext;

    @Autowired
    private CopyPropertyUtils copyPropertyUtils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        if (log.isDebugEnabled())
            log.debug("{}Inside MFS Builder, building Transaction request", CONVERTER);

        copyPropertyUtils.copy(requestContext, transaction);
        
        ..............
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // No implementation is done in post handle of the intercepter
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

        ..................
    }

}

当我们尝试将

RequestContext
复制到
Transaction
时,我们收到此错误

java.lang.IllegalArgumentException: object is not an instance of declaring class
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:352) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.1.jar:6.1.1]
    at com.sixdee.mfs.base.beans.Transaction$$SpringCGLIB$$0.setChannel(<generated>) ~[classes/:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]

接下来是:

[2m2024-03-08T12:37:20.803+05:30[0;39m [31mERROR[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36mc.s.d.b.e.ResponseErrorHandler          [0;39m [2m:[0;39m Resource Not Found : object is not an instance of declaring class CLASS jdk.internal.reflect.NativeMethodAccessorImpl LINE -2 
[2m2024-03-08T12:37:20.836+05:30[0;39m [33m WARN[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36m.m.m.a.ExceptionHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.beans.FatalBeanException: Could not copy property 'channel' from source to target]
[2m2024-03-08T12:37:20.836+05:30[0;39m [32mDEBUG[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36mc.s.m.b.s.e.EventManager                [0;39m [2m:[0;39m Event management is in progress...
[2m2024-03-08T12:37:20.836+05:30[0;39m [31mERROR[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36mo.s.w.s.HandlerExecutionChain           [0;39m [2m:[0;39m HandlerInterceptor.afterCompletion threw exception

org.springframework.aop.AopInvocationException: AOP configuration seems to be invalid: tried calling method [public java.lang.String com.sixdee.mfs.base.beans.Transaction.toString()] on target [RequestContext(statusCode=DFS100, statusType=F, txnId=168421046664246, channelId=1, channel=PORTAL)]

目标 (

Transaction
) 中所需的所有属性均从其父级
TransactionBase
扩展。

  1. 如果我们尝试将这些属性移动到
    Transaction
    ,则不会出现错误。
  2. 当我们尝试将
    new RequestContext()
    复制到
    new Transaction()
    而不是自动装配的 beans 时,没有错误。
  3. 当我们删除
    @Scope
    注释时,副本就可以工作了。
  4. 我们反编译了
    Transaction
    的.class文件,发现没有继承的方法。
  5. 我们将
    Transaction
    的所有注释都给了
    TransactionBase
    ,错误仍然发生。

我们无法找到导致此问题的原因,无论是源问题(Point-3)还是目标问题(Point-1),我们只能了解其中之一对象不可用,属性名称和类型也相同。根据@M的评论。 Deinum 在这篇post中我相信问题出在

org.springframework.beans.BeanUtils
,但答案却说了别的。

我们在某些场景中使用

@Autowired
,在其他一些场景中使用
@AllArgsConstructor
进行依赖注入,这会导致任何问题吗?另外,
RequestContext
是父级maven项目中的一个bean,其他的都在子级maven项目中,这取决于父级。

版本

Java 17

Spring Boot 3.2.0

java spring-boot autowired lombok
1个回答
0
投票

当您使用 ScopedProxyMode.TARGET_CLASS 时,它将使用 CGLIB 创建基于类的代理。因此 Transaction 和 RequestContext 类型的对象不是真正的实例,它们是具体类的代理,就像 Andrew 和 M.Deinum 在评论部分中所说的那样。您需要使用具体实现而不是代理。

© www.soinside.com 2019 - 2024. All rights reserved.