advice详解
bytebuddy实现原理分析 &源码分析(一)
bytebuddy实现原理分析 &源码分析 (二)
bytebuddy实现原理分析 &源码分析 (三)
bytebuddy实现原理分析 &源码分析 (四)
八、advice
增强,切面编程。
asm入门
asm手册
大致了解了asm,就可以知道Visitor
是asm进行读写解析.class
字节码文件的核心api。切面的原理就是匹配所有的方法,在方法前后加入额外的方法,AdviceAdapter
类提供了onMethodEnter
和onMethodExit
两个方法,实现就可以做到简单的切面。
bytebuddy 的增强就是基于 asm的core API然后提供了一些列注解,方法用户使用。
8.1 AsmVisitorWrapper
就是对visitor的一个封装。
visitor
以分为 ClassReader
和ClassWriter
。
首先 提供了一个字段 flags
:代表了标志。
核心方法
- int mergeWriter(int flags); 合并写标记
flags|foo
- int mergeReader(int flags); 合并读标记
- ClassVisitor
wrap
(TypeDescription
instrumentedType,
ClassVisitor
classVisitor,
Implementation.Context
implementationContext,
TypePool
typePool,
FieldList<FieldDescription.InDefinedShape>
fields,
MethodList<?>
methods,
int
writerFlags,
int
readerFlags);
把一个DynamicType
定义的类,使用ClassVisitor
生成字节码。
instrumentedType ,被修改的类型;implementationContext,就是定义了改动的字节码实现;TypePool 缓存池;MethodList 方法列表;
8.1.1 ForDeclareFields
8.1.1.1 Entry
- matcher 用来命中的对象
- FieldVisitorWrapper 的 封装了要被修改filed对应的Vistor。
这个类的作用是报存 matcher和visitor的对应关系。使用matcher命中被修改的区域,visitor来应用修改逻辑。
protected static class Entry implements ElementMatcher<FieldDescription.InDefinedShape>, FieldVisitorWrapper {
/**
* The matcher to identify fields to be wrapped.
*/
private final ElementMatcher<? super FieldDescription.InDefinedShape> matcher;
/**
* The field visitor wrapper to be applied if the given matcher is matched.
*/
private final List<? extends FieldVisitorWrapper> fieldVisitorWrappers;
/**
* Creates a new entry.
*
* @param matcher The matcher to identify fields to be wrapped.
* @param fieldVisitorWrappers The field visitor wrapper to be applied if the given matcher is matched.
*/
protected Entry(ElementMatcher<? super FieldDescription.InDefinedShape> matcher, List<? extends FieldVisitorWrapper> fieldVisitorWrappers) {
this.matcher = matcher;
this.fieldVisitorWrappers = fieldVisitorWrappers;
}
/**
* {@inheritDoc}
*/
public boolean matches(FieldDescription.InDefinedShape target) {
return target != null && matcher.matches(target);
}
/**
* {@inheritDoc}
*/
public FieldVisitor wrap(TypeDescription instrumentedType, FieldDescription.InDefinedShape fieldDescription, FieldVisitor fieldVisitor) {
for (FieldVisitorWrapper fieldVisitorWrapper : fieldVisitorWrappers) {
fieldVisitor = fieldVisitorWrapper.wrap(instrumentedType, fieldDescription, fieldVisitor);
}
return fieldVisitor;
}
}
8.1.1.2 DispatchingVisitor
继承ClassVisitor方法
protected class DispatchingVisitor extends ClassVisitor {
/**
* The instrumented type.
*/
private final TypeDescription instrumentedType;
/**
* A mapping of fields by their name and descriptor key-combination.
*/
private final Map<String, FieldDescription.InDefinedShape> fields;
/**
* Creates a new dispatching visitor.
*/
protected DispatchingVisitor(ClassVisitor classVisitor, TypeDescription instrumentedType, Map<String, FieldDescription.InDefinedShape> fields) {
super(OpenedClassReader.ASM_API, classVisitor);
this.instrumentedType = instrumentedType;
this.fields = fields;
}
@Override
public FieldVisitor visitField(int modifiers, String internalName, String descriptor, String signature, Object defaultValue) {
FieldVisitor fieldVisitor = super.visitField(modifiers, internalName, descriptor, signature, defaultValue);
FieldDescription.InDefinedShape fieldDescription = fields.get(internalName + descriptor);
if (fieldVisitor != null && fieldDescription != null) {
for (Entry entry : entries) {
if (entry.matches(fieldDescription)) {
fieldVisitor = entry.wrap(instrumentedType, fieldDescription, fieldVisitor);
}
}
}
return fieldVisitor;
}
}
- instrumentedType ,是被修改的类。
- fields, 一个map结构,一个fields。
visitField
,使用entry.wrap
最终将fieldVisitor
委托给FieldVisitorWrapper
接口。所以FieldVisitorWrapper
的子类只要实现FieldVisitorWrapper
的wrap
方法,在其中定义具体的修改逻辑。
public interface FieldVisitorWrapper {
/**
* Wraps a field visitor.
*
* @param instrumentedType The instrumented type.
* @param fieldDescription The field that is currently being defined.
* @param fieldVisitor The original field visitor that defines the given field.
* @return The wrapped field visitor.
*/
FieldVisitor wrap(TypeDescription instrumentedType, FieldDescription.InDefinedShape fieldDescription, FieldVisitor fieldVisitor);
}
8.1.1.3 ForDeclaredField 的内部实现
也是封装了上面提到的类
class ForDeclaredFields extends AbstractBase {
/**
* The list of entries that describe matched fields in their application order.
*/
private final List<Entry> entries;
/**
* Creates a new visitor wrapper for declared fields.
*/
public ForDeclaredFields() {
this(Collections.<Entry>emptyList());
}
/**
* Creates a new visitor wrapper for declared fields.
*
* @param entries The list of entries that describe matched fields in their application order.
*/
protected ForDeclaredFields(List<Entry> entries) {
this.entries = entries;
}
/**
* Defines a new field visitor wrapper to be applied if the given field matcher is matched. Previously defined
* entries are applied before the given matcher is applied.
*
* @param matcher The matcher to identify fields to be wrapped.
* @param fieldVisitorWrapper The field visitor wrapper to be applied if the given matcher is matched.
* @return A new ASM visitor wrapper that applied the given field visitor wrapper if the supplied matcher is matched.
*/
public ForDeclaredFields field(ElementMatcher<? super FieldDescription.InDefinedShape> matcher, FieldVisitorWrapper... fieldVisitorWrapper) {
return field(matcher, Arrays.asList(fieldVisitorWrapper));
}
/**
* Defines a new field visitor wrapper to be applied if the given field matcher is matched. Previously defined
* entries are applied before the given matcher is applied.
*
* @param matcher The matcher to identify fields to be wrapped.
* @param fieldVisitorWrappers The field visitor wrapper to be applied if the given matcher is matched.
* @return A new ASM visitor wrapper that applied the given field visitor wrapper if the supplied matcher is matched.
*/
public ForDeclaredFields field(ElementMatcher<? super FieldDescription.InDefinedShape> matcher, List<? extends FieldVisitorWrapper> fieldVisitorWrappers) {
return new ForDeclaredFields(CompoundList.of(entries, new Entry(matcher, fieldVisitorWrappers)));
}
/**
* {@inheritDoc}
*/
public ClassVisitor wrap<