可能是我没有认真思考,还是答案确实难以捉摸。快速场景(尝试代码。进行编译)。

考虑旧版界面

public interface LegacyInterfaceNoCodeAvailable{
    void logInfo(String message);
}

考虑上述接口(interface)的旧版实现
public abstract class LegacyClassNoCodeAvailable implements LegacyInterfaceNoCodeAvailable{

    public abstract void executeSomething();

    public void rockItOldSchool(){
        logInfo("bustin' chops, old-school style");
    }

    @Override
    public void logInfo(String message){
        System.out.println(message);
    }
}

现在,我以这个有抱负的人的身份进来,为"new"系统编写了一个类,但该类在“旧式”框架内运行,因此我必须扩展旧版基类。
public class lass SpankingShiny extends LegacyClassNoCodeAvailable{

    public void executeSomething(){
        rockItOldSchool();
        logInfo("I'm the King around here now");
        System.out.println("this new stuff rocks!!");
    }
}

一切都很好,就像您期望的那样:
SpankingShiny shiny = new SpankingShiny();
shiny.executeSomething();

上面的代码产生(如预期的那样):
bustin' chops, old-school style
I'm the King around here now
this new stuff rocks!!

现在您可以看到,“System.out.println()”忠实地打印了所需的输出。但是我希望用记录器替换'System.out.println()'。

问题:

我无法让CGLIB代理截取到'logInfo(string)'方法,并使其通过记录器打印出我想要的消息(顺便说一句,我已经正确完成了记录配置)。该方法调用“显然”不会命中代理。

代码:
public class SpankingShinyProxy implements MethodInterceptor{

    private SpankingShiny realShiny;
    private final Logger logger = Logger.getLogger(SpankingShinyProxy.class);

    public SpankingShinyProxy(SpankingShiny realShiny) {
        super();
        this.realShiny = realShiny;
    }

    @Override
    public Object intercept(Object proxyObj, Method proxyMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable {
        String methodName = proxyMethod.getName();
        if("logInfo".equals(methodName)){
            logger.info(methodParams[0]);
        }
        return proxyMethod.invoke(realShiny, methodParams);
    }

    public static SpankingShiny createProxy(SpankingShiny realObj){
        Enhancer e = new Enhancer();
        e.setSuperclass(realObj.getClass());
        e.setCallback(new SpankingShinyProxy(realObj));
        SpankingShiny proxifiedObj = (SpankingShiny) e.create();
        return proxifiedObj;
    }
}

主要方法:
public static void main(String... args) {

        SpankingShiny shiny = new SpankingShiny();
        shiny.executeSomething();

        SpankingShiny shinyO = SpankingShinyProxy.createProxy(shiny);
        shinyO.executeSomething();
    }

上面的代码产生(不符合预期):
bustin' chops, old-school style
I'm the King around here now
this new stuff rocks!!
bustin' chops, old-school style
I'm the King around here now
this new stuff rocks!!

我要去哪里错了?

谢谢!

最佳答案

我有同样的问题。就我而言,realObj本身就是一个代理(Spring Bean-@Component)。

因此,我要做的是更改以下内容中的.setSuperClass()部分:

Enhancer e = new Enhancer();
e.setSuperclass(realObj.getClass());
e.setCallback(new SpankingShinyProxy(realObj));
SpankingShiny proxifiedObj = (SpankingShiny) e.create();

我变了:
e.setSuperclass(realObj.getClass());

至:
e.setSuperclass(realObj.getClass().getSuperClass());

如上面所说,之所以起作用是因为realObj.getClass()本身就是CGLIB代理,并且该方法返回了疯狂名称-CGLIB生成的类,例如a.b.c.MyClass$$EnhancerBySpringCGLIB$$1e18666c。当我添加.getSuperClass()时,它返回了该类,它应该首先返回。

关于java - CGLIB无法拦截父类(super class)/ super 接口(interface)中的方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19748853/

10-09 00:25