-
Notifications
You must be signed in to change notification settings - Fork 126
Open
Labels
bugSomething isn't workingSomething isn't working
Milestone
Description
重现方式
写一个匹配interface的@Instrument,比如
@Instrument(Interface = "org.apache.dubbo.rpc.Invoker")
public abstract class Invoker {
/**
* invoke.
*
* @param invocation
* @return result
* @throws RpcException
*/
public Result invoke(Invocation invocation) throws RpcException {
DubboUtils.test(invocation);
System.err.println("invoker class: " + this.getClass().getName());
Result result = InstrumentApi.invokeOrigin();
System.err.println("result:" + result + ", invoker class: " + this.getClass().getName());
return result;
}
}再写一个匹配abstract类的匹配,比如:
@Instrument(Class = "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory")
public class AbstractAutowireCapableBeanFactory {
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
return InstrumentApi.invokeOrigin();
}那么在加载类 org.springframework.beans.factory.support.DefaultListableBeanFactory 时,会经过Invoker的判断
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory对 @Instrument(Interface = "org.apache.dubbo.rpc.Invoker") 的匹配判断比较复杂,因为 interface 可能有多重继承
- 目前的实现比较简单,直接调用loader.loadClass来加载 interface了。
- 导致结果是在 ClassFileTransformer#transform 处理 DefaultListableBeanFactory 时,又加载了 AbstractAutowireCapableBeanFactory ,所以后面 AbstractAutowireCapableBeanFactory 不会被 ClassFileTransformer#transform 处理了!
- 这里 jdk处理的逻辑不符合用户的想像
public class SimpleInterfaceMatcher implements ClassMatcher {
@Override
public boolean match(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) {
loader = ClassLoaderUtils.wrap(loader);
if (classBeingRedefined != null) { // 在retransform 时,可以直接判断
return match(classBeingRedefined);
} else {
// 读取出具体的 类名,还有父类名, 如果有匹配,则返回 true,没有,就返回 false
ClassReader reader = new ClassReader(classfileBuffer);
String clazzName = reader.getClassName();
String superName = reader.getSuperName();
String[] interfacesArray = reader.getInterfaces();
// 如果是接口,则没有需要处理的地方
if ((reader.getAccess() & Opcodes.ACC_INTERFACE) != 0) {
return false;
}
if (interfaces != null && interfaces.contains(clazzName.replace('/', '.'))) {
return true;
}
for (String i : interfacesArray) {
try {
Class<?> interfaceClass = loader.loadClass(i.replace('/', '.'));
if (matchInterface(interfaceClass)) {
return true;
}
} catch (ClassNotFoundException e) {
// ignore
}
}后续
- 需要重新实现 interface匹配的实现,避免加载类
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working