skywalking-agent源码分析
执行顺序图
该顺序图大体内容都有了,缺少最后一步的BootService的生命周期调用,即下面的接口。在这个接口中会有一些服务调用,比如向Gprc注册发送的流程*
1
2
3
4
5
6
7
8
9
|
public interface BootService {
void prepare() throws Throwable;
void boot() throws Throwable;
void onComplete() throws Throwable;
void shutdown() throws Throwable;
}
|
分析
分析中主要讲class Transformer implements AgentBuilder.Transformer
这个实现类中的transform
方法
transform
方法中调用pluginFinder
的find
方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module) {
List<AbstractClassEnhancePluginDefine> pluginDefines = pluginFinder.find(typeDescription, classLoader);
if (pluginDefines.size() > 0) {
DynamicType.Builder<?> newBuilder = builder;
EnhanceContext context = new EnhanceContext();
for (AbstractClassEnhancePluginDefine define : pluginDefines) {
DynamicType.Builder<?> possibleNewBuilder = define.define(typeDescription, newBuilder, classLoader, context);
if (possibleNewBuilder != null) {
newBuilder = possibleNewBuilder;
}
}
if (context.isEnhanced()) {
logger.debug("Finish the prepare stage for {}.", typeDescription.getName());
}
return newBuilder;
}
logger.debug("Matched class {}, but ignore by finding mechanism.", typeDescription.getTypeName());
return builder;
}
|
- 找到所有的
AbstractClassEnhancePluginDefine
实现类,在迭代所有子类,调用子类的define
方法。在define
方法中最主要的方法是enhance
。该方法是抽象方法,由子类ClassEnhancePluginDefine
中调用enhanceClass
和enhanceInstance
。
1
2
3
4
5
6
7
8
9
10
|
@Override
protected DynamicType.Builder<?> enhance(TypeDescription typeDescription,
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
EnhanceContext context) throws PluginException {
newClassBuilder = this.enhanceClass(typeDescription, newClassBuilder, classLoader);
newClassBuilder = this.enhanceInstance(typeDescription, newClassBuilder, classLoader, context);
return newClassBuilder;
}
|
- 调用
enhanceClass
方法。该方法第一步也是最主要的一步调用getStaticMethodsInterceptPoints
。这个方法也是抽象方法。这个方法由具体的插件实现。比如LoadBalancedConnectionProxyInstrumentation
。这个类中会调用getConstructorsInterceptPoints
来获取哪些方法是需要被拦截的。并且通过getMethodsInterceptor
方法返回具体的实现类。这个方法类似AOP做切面处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
private DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription,
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader) throws PluginException {
StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints();
String enhanceOriginClassName = typeDescription.getTypeName();
if (staticMethodsInterceptPoints == null || staticMethodsInterceptPoints.length == 0) {
return newClassBuilder;
}
for (StaticMethodsInterceptPoint staticMethodsInterceptPoint : staticMethodsInterceptPoints) {
String interceptor = staticMethodsInterceptPoint.getMethodsInterceptor();
if (StringUtil.isEmpty(interceptor)) {
throw new EnhanceException("no StaticMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName);
}
if (staticMethodsInterceptPoint.isOverrideArgs()) {
newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher()))
.intercept(
MethodDelegation.withDefaultConfiguration()
.withBinders(
Morph.Binder.install(OverrideCallable.class)
)
.to(new StaticMethodsInterWithOverrideArgs(interceptor))
);
} else {
newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher()))
.intercept(
MethodDelegation.withDefaultConfiguration()
.to(new StaticMethodsInter(interceptor))
);
}
}
return newClassBuilder;
}
|
LoadBalancedConnectionProxyInstrumentation
的实现方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Override protected StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
return new StaticMethodsInterceptPoint[] {
new StaticMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("createProxyInstance");
}
//返回具体的拦截器实现类
@Override public String getMethodsInterceptor() {
return METHOD_INTERCEPTOR;
}
@Override public boolean isOverrideArgs() {
return false;
}
}
};
}
|
- 调用
enhanceInstance
方法。这个方法中最主要的是调用下面的两个方法,一个是对构造器进行切面拦截,另一个是对实例对象中的方法进行拦截。比如InvocableHandlerInstrumentation
这个实现类是对Springmvc中InvocableHandlerMethod
的invokeForRequest
进行拦截,具体的拦截器类是org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor.InvokeForRequestInterceptor
。
1
2
|
ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints();
InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = getInstanceMethodsInterceptPoints();
|
- 实现类中的方法调用,3和4步骤中对方法进行了增强即拦截进行了代理操作。以
enhanceInstance
为例,在调用getConstructorsInterceptPoints
和方法getInstanceMethodsInterceptPoints
之后,如果存在需要拦截的方法,通过返回的newClassBuilder
对方法进行拦截配置。如下代码,newClassBuilder.method(junction).intercept(...)
调用intercept方法,然后在intercept方法中分别调用接口的具体实现方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
if (existedMethodsInterceptPoints) {
for (InstanceMethodsInterceptPoint instanceMethodsInterceptPoint : instanceMethodsInterceptPoints) {
String interceptor = instanceMethodsInterceptPoint.getMethodsInterceptor();
if (StringUtil.isEmpty(interceptor)) {
throw new EnhanceException("no InstanceMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName);
}
ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher());
if (instanceMethodsInterceptPoint instanceof DeclaredInstanceMethodsInterceptPoint) {
junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription));
}
if (instanceMethodsInterceptPoint.isOverrideArgs()) {
newClassBuilder =
newClassBuilder.method(junction)
.intercept(
MethodDelegation.withDefaultConfiguration()
.withBinders(
Morph.Binder.install(OverrideCallable.class)
)
.to(new InstMethodsInterWithOverrideArgs(interceptor, classLoader))
);
} else {
newClassBuilder =
newClassBuilder.method(junction)
.intercept(
MethodDelegation.withDefaultConfiguration()
.to(new InstMethodsInter(interceptor, classLoader))
);
}
}
}
|
总结重要实现及接口
该流程过程中主要是在enhance方法内进程代理(拦截器)的创建。具体的拦截器接口有InstanceConstructorInterceptor
,InstanceMethodsAroundInterceptor
,StaticMethodsAroundInterceptor
,然后在上面三个接口的子类中有些会实现EnhancedInstance
接口进行动态属性添加。而最主要的三个接口的实现类的调用是通过newClassBuilder.method(junction).intercept
方法内部调用的。
如下图: