Java Spring aop,cglib增强类丢失通用信息

Java Spring aop,cglib增强类丢失通用信息,java,json,spring,struts2,cglib,Java,Json,Spring,Struts2,Cglib,我有一个struts 2 action类: public class MyAction{ private ArrayList<User> users; public void setUsers(ArrayList<User> users){ this.users = users; } public String doMyAction(){ //... } } 在这一行: Type[] generic

我有一个struts 2 action类:

public class MyAction{
    private ArrayList<User> users;
    public void setUsers(ArrayList<User> users){
        this.users = users;
    }
    public String doMyAction(){
        //...
    }
}
在这一行:

Type[] genericTypes = method.getGenericParameterTypes();
启用AOP时,它会根据
users
字段的setter方法返回
java.util.ArrayList
。但是
java.util.ArrayList

当cglib代理时,我的action类似乎丢失了它的通用信息。我也发现了这个


我可以从aop配置中排除我的方法来解决这个问题。但我仍然想知道是否有更好的解决方案?

Cglib是在泛型类型存在之前创建的。代理作为cglib中代理类的子类生成,该类不保留泛型类型信息。因此,您无法从proxy类查询它。

我的想法是尝试查找代理背后的实际类型。根据spring文档,从SpringAOP获得的任何代理都实现了
org.springframework.aop.framework.Advised
接口,该接口公开了查询目标类的方法

Any AOP proxy obtained from Spring can be cast to this interface to allow manipulation of its AOP advice.
因此这里我们有一个相当大的选择,我们可以下载struts json插件源代码并构建我们自己的源代码,修改
JSONPopulator的
populateObject
方法

public void populateObject(Object object, final Map elements) throws IllegalAccessException,
            InvocationTargetException, NoSuchMethodException, IntrospectionException,
            IllegalArgumentException, JSONException, InstantiationException {

        Class clazz = object.getClass();

        // if it is a proxy, find the actual type behind it
        if(Advised.class.isAssignableFrom(clazz)){
            clazz = ((Advised)object).getTargetSource().getTargetClass();
        }

        BeanInfo info = Introspector.getBeanInfo(clazz);
        PropertyDescriptor[] props = info.getPropertyDescriptors();

        // iterate over class fields
        for (int i = 0; i < props.length; ++i) {
            PropertyDescriptor prop = props[i];
            String name = prop.getName();

            if (elements.containsKey(name)) {
                Object value = elements.get(name);
                Method method = prop.getWriteMethod();

                if (method != null) {
                    JSON json = method.getAnnotation(JSON.class);
                    if ((json != null) && !json.deserialize()) {
                        continue;
                    }

                    // use only public setters
                    if (Modifier.isPublic(method.getModifiers())) {
                        Class[] paramTypes = method.getParameterTypes();


                        Type[] genericTypes = method.getGenericParameterTypes();

                        if (paramTypes.length == 1) {
                            Object convertedValue = this.convert(paramTypes[0], genericTypes[0], value,
                                    method);
                            method.invoke(object, new Object[] { convertedValue });
                        }
                    }
                }
            }
        }
    }
public void populateObject(Object object, final Map elements) throws IllegalAccessException,
            InvocationTargetException, NoSuchMethodException, IntrospectionException,
            IllegalArgumentException, JSONException, InstantiationException {

        Class clazz = object.getClass();

        // if it is a proxy, find the actual type behind it
        if(Advised.class.isAssignableFrom(clazz)){
            clazz = ((Advised)object).getTargetSource().getTargetClass();
        }

        BeanInfo info = Introspector.getBeanInfo(clazz);
        PropertyDescriptor[] props = info.getPropertyDescriptors();

        // iterate over class fields
        for (int i = 0; i < props.length; ++i) {
            PropertyDescriptor prop = props[i];
            String name = prop.getName();

            if (elements.containsKey(name)) {
                Object value = elements.get(name);
                Method method = prop.getWriteMethod();

                if (method != null) {
                    JSON json = method.getAnnotation(JSON.class);
                    if ((json != null) && !json.deserialize()) {
                        continue;
                    }

                    // use only public setters
                    if (Modifier.isPublic(method.getModifiers())) {
                        Class[] paramTypes = method.getParameterTypes();


                        Type[] genericTypes = method.getGenericParameterTypes();

                        if (paramTypes.length == 1) {
                            Object convertedValue = this.convert(paramTypes[0], genericTypes[0], value,
                                    method);
                            method.invoke(object, new Object[] { convertedValue });
                        }
                    }
                }
            }
        }
    }
 // if it is a proxy, find the actual type behind it
            if(Advised.class.isAssignableFrom(clazz)){
                clazz = ((Advised)object).getTargetSource().getTargetClass();
            }