Spring - JDK接口和CGLIB代理的组合

时间:2016-07-21 12:52:54

标签: java spring interface proxy cglib

我们最近从一个非常古老的Spring版本(3.2.16.RELEASE)迁移到了最新版本(4.2.5.RELEASE)之一。由于这一变化,我们能够在一些.xml文件中删除超过1k行的代码,并用Java类中的大约50-100个注释替换它们。总而言之,这是一个很大的改变。

昨天我也开始删除@Service - 注释添加的所有接口。所以,在我们有这样的事情之前:

//The interface:
public interface SomeInterfaceService extends DtoProcessingService<SimpleDto> {
}

//The class:
@Service("someClassService")
public class SomeClassService
    extends SomeAbstractClassService<SimpleDto, Strategy>
    implements SomeInterfaceService {
  ...
}

我们已经重构为:

// The interface has been removed

//The class:
@Service
public class SomeClassService
    extends SomeAbstractClassService<SimpleDto, Stategy> {
  ...
}

在新的Spring版本中,@Service自动使用以小写字母开头的类名(所以someClassService)。

起初我们收到了一些错误,可能的解决办法是使用Spring xml设置来显式使用代理类。所以,我已经读过一些关于这些代理的力量所暗示的内容,并发现了以下内容:

  

...根据项目页面&#34; CGLIB用于扩展Java类并在运行时实现接口&#34;。因此,在这种情况下,诀窍在于创建一个 EXTENDS 原始对象的代理,因此可以使用它。 (source

     

1)final方法无法建议,因为它们无法覆盖。 (source
  2)您将在类路径上需要CGLIB 2二进制文件,而JDK可以使用动态代理。 Spring会在需要CGLIB时自动发出警告,并且在类路径中找不到CGLIB库类。 (source
  3)代理对象的构造函数将被调用两次。这是CGLIB代理模型的自然结果,其中为每个代理对象生成子类。对于每个代理实例,创建两个对象:实际代理对象和实现建议的子类实例。使用JDK代理时不会出现此行为。通常,两次调用代理类型的构造函数不是问题,因为通常只有赋值发生,并且构造函数中没有实现真正的逻辑。 (source
  4)您的课程不能是final。 (source 1&amp; source 2

我们的课程都没有final,他们的方法都没有final,没有一个类有隐式的构造函数,所以我已将此设置添加到Spring xml中:

 <tx:annotation-driven proxy-target-class="true"/>

错误消失了。

现在我有一些问题和疑虑:
有些类/接口有点难以重构,所以我们将它们保留原样(现在)。这些主要是具有大量泛型,抽象的类树,因此难以轻易地重构。此外,还有一些其他类的接口,我甚至还没有触及它仍然使用接口 使用上述设置是否可以同时使用CGLIB个代理和JDK接口?

我的猜测并非完全如此。为什么?带接口的类似乎仍然是初始化的,但是以前用Spring / Tapestry自动填充的字段不再适用于这些类(我到处都是NullPointerExceptions)。例如,以下用于在更改之前正常工作,但geometryMessageService现在是null

// Note that this is an unchanged class

@Transactional
@Service("geometryService")
public class DefaultGeometryService implements GeometryService {
  ...

  private GeometryMessageService geometryMessageService;

  public void setGeometryBerichtService(final GeometryBerichtService geometryBerichtService) {
    this.geometryBerichtService = geometryBerichtService;
  }

  public void someMethod(){
    ...
    this.geometryBerichtService.doSomething(); // <- NullPointerException
    ...
  }
}

0 个答案:

没有答案