ProxyGenerator生成代理问题

public class ProxyGenerator {
    protected boolean isSkipMethod(Method method) {
        int mod = method.getModifiers();
        if ( ! Modifier.isPublic(mod) ) {
           return true;
        }
        
        if (Modifier.isFinal(mod) || Modifier.isStatic(mod) || Modifier.isAbstract(mod)) {
           return true;
        }
    
        /*
         * 当子类重写父类方法时,应只增强子类方法。
         * 若都不做处理,则会都增强,导致出现异常:
         * 名称冲突: class UserService$$Enhancer 的两种方法具有相同的疑符, 但两者均不覆盖对方
         *     public  boolean deleteById(java.lang.String p0) {
         *             ^
         * 第一种方法: top.xpman.service.impl.BaseService 中的 deleteById(java.lang.String)
         * 第二种方法: top.xpman.service.UserService$$Enhancer 中的 deleteById(java.lang.Object)
         *
         * 示例代码:
         * class BaseService<T extends Model<T>, ID> {
         *     public T findById(ID id) {
         *            // default process
         *     }
         * }
         *
         * class UserService extends BaseService<User, String> {
         *     @Override
         *     @Before(CacheInterceptor.class)
         *     public User findById(String id) {
         *            // process
         *     }
         * }
         *
         * 运行时获取到类的方法:
         * @Before(CacheInterceptor.class)
         * public Model findById(Object id);
         * // 4196 = 1(public) & 64(0x0040: volatile) & 4096(0x1000: synthetic)
         * modifiers: 4161
         * ......
         *
         * @Before(CacheInterceptor.class)
         * public User findById(String id);
         * // 1: public
         * modifiers: 1
         * ......
         *
         * Modifier.isSynthetic() => modifiers & 4096 != 0
         *
         * 由于时间关系并未深究与测试,这里简单粗暴处理一下,
         * 此处应该校验一下是否有签名一致的方法才对
         * todo 2023/03/04
         */
        final int modifiers = 4096;
        if ((modifiers & mod) != 0) {
           log.debug("Skip Synthetic Method: {}", method);
           return true;
        }
        
        String n = method.getName();
        if (n.equals("toString") || n.equals("hashCode") || n.equals("equals")) {
           return true;
        }
        
        return false;
    }
}


评论区

JFinal

2024-06-17 10:02

代理建议用后来新增的 javassist 代理实现,阿里这些大厂用的这个,配置一下:
me.setToJavassistProxyFactory();

新框架 aifei 已经将默认代理切到 javassist 了,原先的动态编译不再使用,主要原因还是动态编译依赖 JDK,而有些 docker 服务端生产环境可能安装的是 JRE

chcode

2024-06-17 16:54

@JFinal 可惜了基于模版的动态代理还是很有创意的

JFinal

2024-06-17 17:34

@chcode 确实可惜,还有一个原因是 aifei 内核尽可能是纯抽象代码,所以动态代理这类实现被放在 aifei-base 等周边项目之中

而周边项目,我并不打算做到对任何第三无依赖,所以用用 javassist 变成可接受的

最终,只要确保 aifei 内核是完美的就可以了

JFinal

2024-06-17 17:37

之前的 jfinal 由于是 all in one 项目,而一直要确保 jfinal 自身没有任何第三方依赖,所以必须要无第三依赖地方式去实现动态代理

从这个角度上验证了:严苛的限制条件可激发创新

这个问题还导致了我有新的创作思路,完美的东西放 aifei 内核,不完美的东西放内核之外,这样极大减轻了工作量

lyh061619

2024-06-17 23:30

@JFinal 原先的动态编译可以保留作为可选方案续继存在

BTMTimor

2024-06-18 10:48

@JFinal aifei框架啥时候能来个bete版体验下

热门反馈

扫码入社