Preface
I was writing before --> talk about how spi based on jdk integrates with spring to realize dependency injection . When the demo of this article was used, dynamic proxy was used. During debugging, I found a magical phenomenon. As shown below
The proxy object becomes null, but there will be no null pointer exception
Phenomenon analysis
First look at the core implementation logic of the sample agent
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean canPass = preHandle(method,args);
Object result = null;
if(canPass){
result = method.invoke(target,args);
afterCompletion(method,args);
}
return result;
}
When this logic is false, result will be null. The idea is to enable debugging. When calls an object, the toString method is called by default. When the proxy triggers invoke, because preHandle cannot find the toString method, it will cause canPass to be false, which triggers a null phenomenon.
Say there is no proof, we can verify, we adjust the core method of the agency
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("toString".equals(method.getName())){
return "我是toString方法";
}
boolean canPass = preHandle(method,args);
Object result = null;
if(canPass){
result = method.invoke(target,args);
afterCompletion(method,args);
}
return result;
}
Do dubug at this time, as shown below
Problem fix
1. Method 1: Disable the default call toString method of idea
2. Method 2: In the proxy invoke method, add the following code snippets as follows
// 如果Object方法直接反射调用
if(Object.class.equals(method.getDeclaringClass())){
return method.invoke(this, args);
}
This kind of solution, the dynamic agent implemented in mybatis has appeared
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (method.isDefault()) {
if (privateLookupInMethod == null) {
return invokeDefaultMethodJava8(proxy, method, args);
} else {
return invokeDefaultMethodJava9(proxy, method, args);
}
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
The above is taken from the MapperProxy proxy fragment of mybatis
Summarize
Be more curious and look at the source code
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。