java - cglib 创建的 spring bean 抛出 no such method 异常

标签 java spring cglib

我有几十个类,如下所示:

@Repository("jobProcessingDao")
@Transactional(readOnly = true)
public class JobProcessingDaoImpl extends BaseDaoImpl implements JobProcessingDao {
/*implementation interface methods*/   
}

仅此一个发生异常(并且仅此一个是由 cglib 生成的)。

其实,为什么spring使用cglib代理而不是jdk呢?我的类实现了接口(interface),并且我相信我没有为 ProxyFactoryBeanproxyInterfaces 设置任何值。

无论如何,我从 DefaultGeneratorStrategy#generate 类以字节格式获取,这就是我实际得到的:

behemoth@Anechka ~ $ javap -c xf.class
Compiled from "<generated>"
public class package_name.dataaccesscomponent.impl.JobProcessingDaoImpl$$EnhancerByCGLIB$$f8ed98b3 extends package_name.dataaccesscomponent.impl.JobProcessingDaoImpl implements org.springframework.context.annotation.ConfigurationClassEnhancer$EnhancedConfiguration {
  static void CGLIB$STATICHOOK2();
    Code:
       0: new           #22                 // class java/lang/ThreadLocal
       3: dup
       4: invokespecial #25                 // Method java/lang/ThreadLocal."<init>":()V
       7: putstatic     #27                 // Field CGLIB$THREAD_CALLBACKS:Ljava/lang/ThreadLocal;
      10: iconst_0
      11: anewarray     #61                 // class java/lang/Object
      14: putstatic     #49                 // Field CGLIB$emptyArgs:[Ljava/lang/Object;
      17: ldc           #77                 // String package_name.impl.JobProcessingDaoImpl$$EnhancerByCGLIB$$f8ed98b3
      19: invokestatic  #83                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
      22: astore_0
      23: iconst_2
      24: anewarray     #85                 // class java/lang/String
      27: dup
      28: iconst_0
      29: ldc           #86                 // String destroy
      31: aastore
      32: dup
      33: iconst_1
      34: ldc           #87                 // String ()V
      36: aastore
      37: ldc           #89                 // String org.springframework.beans.factory.DisposableBean
      39: invokestatic  #83                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
      42: dup
      43: astore_1
      44: invokevirtual #93                 // Method java/lang/Class.getDeclaredMethods:()[Ljava/lang/reflect/Method;
      47: invokestatic  #99                 // Method net/sf/cglib/core/ReflectUtils.findMethods:([Ljava/lang/String;[Ljava/lang/reflect/Method;)[Ljava/lang/reflect/Method;
      50: dup
      51: iconst_0
      52: aaload
      53: putstatic     #47                 // Field CGLIB$destroy$10$Method:Ljava/lang/reflect/Method;
      56: aload_1
      57: aload_0
      58: ldc           #87                 // String ()V
      60: ldc           #86                 // String destroy
      62: ldc           #100                // String CGLIB$destroy$10
      64: invokestatic  #106                // Method net/sf/cglib/proxy/MethodProxy.create:(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lnet/sf/cglib/proxy/MethodProxy;
      67: putstatic     #51                 // Field CGLIB$destroy$10$Proxy:Lnet/sf/cglib/proxy/MethodProxy;
      70: pop
      71: return
      72: return

  final void CGLIB$destroy$10() throws java.lang.Exception;
    Code:
       0: aload_0
       1: invokespecial #39                 // Method package_name/dataaccesscomponent/impl/JobProcessingDaoImpl.destroy:()V
       4: return

  public final void destroy() throws java.lang.Exception;
    Code:
       0: aload_0
       1: getfield      #41                 // Field CGLIB$CALLBACK_1:Lnet/sf/cglib/proxy/MethodInterceptor;
       4: dup
       5: ifnonnull     17
       8: pop
       9: aload_0
      10: invokestatic  #45                 // Method CGLIB$BIND_CALLBACKS:(Ljava/lang/Object;)V
      13: aload_0
      14: getfield      #41                 // Field CGLIB$CALLBACK_1:Lnet/sf/cglib/proxy/MethodInterceptor;
      17: dup
      18: ifnull        37
      21: aload_0
      22: getstatic     #47                 // Field CGLIB$destroy$10$Method:Ljava/lang/reflect/Method;
      25: getstatic     #49                 // Field CGLIB$emptyArgs:[Ljava/lang/Object;
      28: getstatic     #51                 // Field CGLIB$destroy$10$Proxy:Lnet/sf/cglib/proxy/MethodProxy;
      31: invokeinterface #57,  5           // InterfaceMethod net/sf/cglib/proxy/MethodInterceptor.intercept:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;
      36: return
      37: aload_0
      38: invokespecial #39                 // Method package_name/dataaccesscomponent/impl/JobProcessingDaoImpl.destroy:()V
      41: return

  public static net.sf.cglib.proxy.MethodProxy CGLIB$findMethodProxy(net.sf.cglib.core.Signature);
    Code:
       0: aload_0
       1: invokevirtual #65                 // Method java/lang/Object.toString:()Ljava/lang/String;
       4: dup
       5: invokevirtual #69                 // Method java/lang/Object.hashCode:()I
       8: tableswitch   { // 1460027707 to 1460027707
            1460027707: 28
               default: 40
          }
      28: ldc           #71                 // String destroy()V
      30: invokevirtual #75                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
      33: ifeq          41
      36: getstatic     #51                 // Field CGLIB$destroy$10$Proxy:Lnet/sf/cglib/proxy/MethodProxy;
      39: areturn
      40: pop
      41: aconst_null
      42: areturn

  public package_name.dataaccesscomponent.impl.JobProcessingDaoImpl$$EnhancerByCGLIB$$f8ed98b3();
    Code:
       0: aload_0
       1: dup
       2: invokespecial #107                // Method package_name/dataaccesscomponent/impl/JobProcessingDaoImpl."<init>":()V
       5: invokestatic  #45                 // Method CGLIB$BIND_CALLBACKS:(Ljava/lang/Object;)V
       8: return

  public static void CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]);
    Code:
       0: getstatic     #27                 // Field CGLIB$THREAD_CALLBACKS:Ljava/lang/ThreadLocal;
       3: aload_0
       4: invokevirtual #112                // Method java/lang/ThreadLocal.set:(Ljava/lang/Object;)V
       7: return

  public static void CGLIB$SET_STATIC_CALLBACKS(net.sf.cglib.proxy.Callback[]);
    Code:
       0: aload_0
       1: putstatic     #115                // Field CGLIB$STATIC_CALLBACKS:[Lnet/sf/cglib/proxy/Callback;
       4: return

  static {};
    Code:
       0: invokestatic  #131                // Method CGLIB$STATICHOOK2:()V
       3: return
}

所以当我看到 cglibs 生成的类扩展了我的类时,这个类怎么可能没有这样的方法(在我的类中所有方法都是公共(public)的)?

异常:

Caused by: java.lang.NoSuchMethodError: pakcage_name.dataaccesscomponent.JobProcessingDao.save(Lpakcage_name/businessentities/JobProcessing;)J
    at package_name.synchandler.impl.SyncHandlerImpl.createCompositeJobProcessing(SyncHandlerImpl.java:1232)

附注 Spring 3.1.0.RELEASE

最佳答案

我不能说我可以根据所提供的信息真正回答您的问题。但我可以说:

  • Jdk 代理比 CGLIB 代理更快

  • 不能为类创建 Jdk 代理,只能为接口(interface)创建。

  • Spring 将始终青睐 JDK 代理(因为它们显然更快:))。但如果无法创建 JDK 代理,它将使用 CGLIB。

因此,除非它不是 Spring 中的错误或其他问题,否则我认为您应该看看使用 JobProcessingDaoImpl 的类。很可能相关的数据字段不是通过接口(interface)连接的,而是通过类,所以 Spring 没有选择,它必须使用 CGLIB。

我认为您还应该检查运行时(使用调试器或其他东西)其他 DAO 实现 - 也许它们全部都用 JDK 代理包装。

关于java - cglib 创建的 spring bean 抛出 no such method 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37350166/

相关文章:

java - 如何将 Vector 更改为 ArrayList?

java - 在给定的字符串日期中获取该月的最后一天

java - 使用 lambda 创建包含空对象的 ArrayList

spring - org.springframework.beans.factory.BeanCreationException : Error creating bean with name 'jedisClientPool' defined in class path resource

java - Spring:将值作为对象形式映射并传递给 Controller ​​以进行查看

java - 为什么在 JBoss 7.1.EAP 中运行应用程序时出现 java.lang.NoSuchMethodError

Java/cglib 只调用 super 时忽略方法?

java - 如何监控HTTP连接池?

Spring Java 配置、@Autowire 与构造函数注入(inject)、@Transactional 和 CGLIB

java - 如何为 java.nio.ByteBuffer 实例创建一个 java 代理对象?