可能是我没有认真思考,还是答案确实难以捉摸。快速场景(尝试代码。进行编译)。
考虑旧版界面
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/