Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring,CGLIB:why can';不能代理泛型类吗?_Java_Spring_Cglib - Fatal编程技术网

Java Spring,CGLIB:why can';不能代理泛型类吗?

Java Spring,CGLIB:why can';不能代理泛型类吗?,java,spring,cglib,Java,Spring,Cglib,我想问一下异常的根本原因: 原因:java.lang.ClassCastException:java.lang.Class无法强制转换为 java.lang.reflect.ParameterizedType 在Spring中,当我们让Spring为类生成代理(即在事务管理器上设置proxy target class=“true”)时,会发生这种情况: 当要代理的类是参数化类时,即 public类SomeDAOImpl实现SomeDAO。。。 例如,完整的故事可以在以下问题中阅读: 问题

我想问一下异常的根本原因:

原因:java.lang.ClassCastException:java.lang.Class无法强制转换为
java.lang.reflect.ParameterizedType
在Spring中,当我们让Spring为类生成代理(即在事务管理器上设置
proxy target class=“true”
)时,会发生这种情况:


当要代理的类是参数化类时,即

public类SomeDAOImpl实现SomeDAO。。。
例如,完整的故事可以在以下问题中阅读:

问题:为什么Spring不能代理这个类?是因为它使用旧的代码生成库吗?因为类型擦除?如果
SomeDAOImpl
不是泛型类,它将成功(我检查了它)


请不要这样回答:“您应该代理接口,而不是类”。我知道。

这看起来像是Spring/CGLIB的问题,但问题实际上在您的构造函数中!我猜您正在尝试获取参数类型,以便将其提供给实体管理器(或您尝试使用的任何持久性框架)。我还猜,要做到这一点,您需要调用
getGenericSuperclass()
并将其强制转换为参数化类型

方法的行为方式取决于类。事实证明,并不是所有类对象都实现ParameterizedType接口(我同意,这很奇怪)。生成的CGLIB代理不保留泛型信息。它看起来像:

public class SomeDAOImplProxy extends SomeDAOImpl
我不知道为什么CGLIB代理不保留泛型,因为CGLIB代理的细节非常复杂。这可能是根本不可能做到的。也可能是这样做不是他们的优先事项

下面是一个简单的实验,它去掉了Spring和CGLIB,但仍然得到了那个错误

public static void main(String [] args) {
    List<Object> fooList = new ArrayList<Object>();
    String fooString = "";
    System.out.println((ParameterizedType)fooList.getClass().getGenericSuperclass());
    System.out.println((ParameterizedType)fooString.getClass().getGenericSuperclass());
}
publicstaticvoidmain(字符串[]args){
列表列表=新的ArrayList();
字符串fooString=“”;
System.out.println((ParameterizedType)doulist.getClass().getGenericSuperclass());
System.out.println((ParameterizedType)fooString.getClass().getGenericSuperclass());
}

这看起来像是Spring/CGLIB问题,但问题实际上在您的构造函数中!我猜您正在尝试获取参数类型,以便将其提供给实体管理器(或您尝试使用的任何持久性框架)。我还猜,要做到这一点,您需要调用
getGenericSuperclass()
并将其强制转换为参数化类型

方法的行为方式取决于类。事实证明,并不是所有类对象都实现ParameterizedType接口(我同意,这很奇怪)。生成的CGLIB代理不保留泛型信息。它看起来像:

public class SomeDAOImplProxy extends SomeDAOImpl
我不知道为什么CGLIB代理不保留泛型,因为CGLIB代理的细节非常复杂。这可能是根本不可能做到的。也可能是这样做不是他们的优先事项

下面是一个简单的实验,它去掉了Spring和CGLIB,但仍然得到了那个错误

public static void main(String [] args) {
    List<Object> fooList = new ArrayList<Object>();
    String fooString = "";
    System.out.println((ParameterizedType)fooList.getClass().getGenericSuperclass());
    System.out.println((ParameterizedType)fooString.getClass().getGenericSuperclass());
}
publicstaticvoidmain(字符串[]args){
列表列表=新的ArrayList();
字符串fooString=“”;
System.out.println((ParameterizedType)doulist.getClass().getGenericSuperclass());
System.out.println((ParameterizedType)fooString.getClass().getGenericSuperclass());
}

由于CGLIB对类进行子类化以生成代理,因此必须获取超类的泛型超类才能获取
参数化类型

public class MyCglibProxiedBean<T> {

    private final Class<T> paramClass;

    public MyCglibProxiedBean() {
        Type genericSuperClass = getClass().getGenericSuperclass();

        // Get the generic super class of the super class if it's a cglib proxy
        if (getClass().getName().contains("$$EnhancerByCGLIB$$")) {
            genericSuperClass = getClass().getSuperclass().getGenericSuperclass();
        }

        this.paramClass = (Class<T>) ((ParameterizedType) genericSuperClass).getActualTypeArguments()[0];
    }
}
公共类MyCglibProxiedBean{
私人期末班;
公共MyCglibProxiedBean(){
类型genericSuperClass=getClass().getGenericSuperclass();
//如果是cglib代理,则获取该超类的泛型超类
如果(getClass().getName()包含(“$$EnhancerByGlib$$”){
genericSuperClass=getClass().getSuperclass().getGenericSuperclass();
}
this.paramClass=(Class)((ParameterizedType)genericSuperClass).getActualTypeArguments()[0];
}
}

由于CGLIB对类进行子类化以生成代理,因此必须获取超类的泛型超类才能获取
参数化类型

public class MyCglibProxiedBean<T> {

    private final Class<T> paramClass;

    public MyCglibProxiedBean() {
        Type genericSuperClass = getClass().getGenericSuperclass();

        // Get the generic super class of the super class if it's a cglib proxy
        if (getClass().getName().contains("$$EnhancerByCGLIB$$")) {
            genericSuperClass = getClass().getSuperclass().getGenericSuperclass();
        }

        this.paramClass = (Class<T>) ((ParameterizedType) genericSuperClass).getActualTypeArguments()[0];
    }
}
公共类MyCglibProxiedBean{
私人期末班;
公共MyCglibProxiedBean(){
类型genericSuperClass=getClass().getGenericSuperclass();
//如果是cglib代理,则获取该超类的泛型超类
如果(getClass().getName()包含(“$$EnhancerByGlib$$”){
genericSuperClass=getClass().getSuperclass().getGenericSuperclass();
}
this.paramClass=(Class)((ParameterizedType)genericSuperClass).getActualTypeArguments()[0];
}
}

我们使用的解决方案与类似,但更通用一点:

Type genericSuperClass = repositoryClass.getGenericSuperclass();
ParameterizedType parametrizedType;
if (genericSuperClass instanceof ParameterizedType) { // class
    parametrizedType = (ParameterizedType) genericSuperClass;
} else if (genericSuperClass instanceof Class) { // in case of CGLIB proxy
    parametrizedType = (ParameterizedType) ((Class<?>) genericSuperClass).getGenericSuperclass();
} else {
    throw new IllegalStateException("class " + repositoryClass + " is not subtype of ParametrizedType.");
}

@SuppressWarnings("unchecked")
Class<T> entityClass = (Class<T>) parametrizedType.getActualTypeArguments()[0];
return entityClass;
Type genericSuperClass=repositoryClass.getGenericSuperclass();
参数化类型参数化类型;
if(参数化类型的genericSuperClass实例){//class
ParameterizedType=(ParameterizedType)genericSuperClass;
}else if(genericSuperClass instanceof Class){//对于CGLIB代理
ParameterizedType=(ParameterizedType)((类)genericSuperClass.getGenericSuperclass();
}否则{
抛出新的IllegalStateException(“类”+repositoryClass+”不是ParameterizedType的子类型。”);
}
@抑制警告(“未选中”)
类entityClass=(类)ParameterizedType.getActualTypeArguments()[0];
返回实体类;

我们使用的解决方案与类似,但更通用一点:

Type genericSuperClass = repositoryClass.getGenericSuperclass();
ParameterizedType parametrizedType;
if (genericSuperClass instanceof ParameterizedType) { // class
    parametrizedType = (ParameterizedType) genericSuperClass;
} else if (genericSuperClass instanceof Class) { // in case of CGLIB proxy
    parametrizedType = (ParameterizedType) ((Class<?>) genericSuperClass).getGenericSuperclass();
} else {
    throw new IllegalStateException("class " + repositoryClass + " is not subtype of ParametrizedType.");
}

@SuppressWarnings("unchecked")
Class<T> entityClass = (Class<T>) parametrizedType.getActualTypeArguments()[0];
return entityClass;
Type genericSuperClass=repositoryClass.getGenericSuperclass();
参数化类型参数化类型;
if(参数化类型的genericSuperClass实例){//class
ParameterizedType=(ParameterizedType)genericSuperClass;
}else如果(类的genericSuperClass实例){//