methodRef,
134 | Object target,
135 | Object[] params,
136 | Throwable throwExp) {
137 | return new Advice(
138 | loader,
139 | clazzRef,
140 | methodRef,
141 | target,
142 | params,
143 | null, //returnObj
144 | throwExp,
145 | ACCESS_AFTER_THROWING
146 | );
147 | }
148 |
149 | /**
150 | * 获取Java类
151 | *
152 | * @return Java Class
153 | */
154 | public Class> getClazz() {
155 | return clazzRef.get();
156 | }
157 |
158 | /**
159 | * 获取Java方法
160 | *
161 | * @return Java Method
162 | */
163 | public GaMethod getMethod() {
164 | return methodRef.get();
165 | }
166 |
167 |
168 | /**
169 | * 本次调用是否支持阿里巴巴中间件鹰眼系统
170 | *
171 | * @return true:支持;false:不支持;
172 | */
173 | public boolean isAliEagleEyeSupport() {
174 | return AliEagleEyeUtils.isEagleEyeSupport(aliEagleEyeTraceIdRef.get());
175 | }
176 |
177 | /**
178 | * 获取本次调用阿里巴巴中间件鹰眼跟踪号
179 | *
180 | * @return 本次调用阿里巴巴中间件鹰眼跟踪号
181 | */
182 | public String getAliEagleEyeTraceId() {
183 | return aliEagleEyeTraceIdRef.get();
184 | }
185 |
186 | /**
187 | * 本次调用是否支持中间件跟踪
188 | * 在很多大公司中,会有比较多的中间件调用链路渲染技术用来记录和支撑分布式调用场景下的系统串联
189 | * 用于串联各个系统调用的一般是一个全局唯一的跟踪号,如果当前调用支持被跟踪,则返回true;
190 | *
191 | * 在阿里中,进行跟踪的调用号被称为EagleEye
192 | *
193 | * @return true:支持被跟踪;false:不支持
194 | */
195 | public boolean isTraceSupport() {
196 | return GlobalOptions.isEnableTraceId
197 | && isAliEagleEyeSupport();
198 | }
199 |
200 | /**
201 | * {{@link #getAliEagleEyeTraceId()}} 的别名,方便命令行使用
202 | *
203 | * @return 本次调用的跟踪号
204 | */
205 | public String getTraceId() {
206 | return getAliEagleEyeTraceId();
207 | }
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.github.ompc.greys
7 | greys
8 | 1.0.0-SNAPSHOT
9 | pom
10 |
11 | greys
12 | https://github.com/oldmanpushcart/greys-anatomy
13 |
14 |
15 | UTF-8
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | junit
62 | junit
63 | 4.9
64 | test
65 |
66 |
67 | net.sf.jopt-simple
68 | jopt-simple
69 | 4.3
70 |
71 |
72 | org.ow2.asm
73 | asm
74 | 5.0.3
75 |
76 |
77 | org.ow2.asm
78 | asm-commons
79 | 5.0.3
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | org.ow2.asm
89 | asm-util
90 | 5.0.3
91 |
92 |
93 | org.apache.commons
94 | commons-lang3
95 | 3.4
96 |
97 |
98 | commons-io
99 | commons-io
100 | 2.4
101 |
102 |
103 | jline
104 | jline
105 | 2.12
106 |
107 |
108 | ognl
109 | ognl
110 | 3.0.8
111 |
112 |
113 | org.slf4j
114 | slf4j-api
115 | 1.7.5
116 |
117 |
118 | ch.qos.logback
119 | logback-classic
120 | 1.0.13
121 |
122 |
123 | ch.qos.logback
124 | logback-core
125 | 1.0.13
126 |
127 |
128 | com.google.code.gson
129 | gson
130 | 2.3.1
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | core
158 | agent
159 |
160 |
--------------------------------------------------------------------------------
/core/src/main/java/com/github/ompc/greys/core/manager/impl/DefaultReflectManager.java:
--------------------------------------------------------------------------------
1 | package com.github.ompc.greys.core.manager.impl;
2 |
3 | import com.github.ompc.greys.core.ClassDataSource;
4 | import com.github.ompc.greys.core.GlobalOptions;
5 | import com.github.ompc.greys.core.manager.ReflectManager;
6 | import com.github.ompc.greys.core.util.GaCheckUtils;
7 | import com.github.ompc.greys.core.util.GaMethod;
8 | import com.github.ompc.greys.core.util.matcher.Matcher;
9 |
10 | import java.lang.reflect.Constructor;
11 | import java.lang.reflect.Method;
12 | import java.lang.reflect.Modifier;
13 | import java.util.Collection;
14 | import java.util.Iterator;
15 | import java.util.LinkedHashSet;
16 | import java.util.Set;
17 |
18 | import static com.github.ompc.greys.core.util.GaReflectUtils.recGetSuperClass;
19 |
20 | /**
21 | * 默认反射操作管理类实现
22 | * Created by vlinux on 15/11/1.
23 | */
24 | public class DefaultReflectManager implements ReflectManager {
25 |
26 | private final ClassDataSource classDataSource;
27 |
28 | public DefaultReflectManager(ClassDataSource classDataSource) {
29 | this.classDataSource = classDataSource;
30 | }
31 |
32 | @Override
33 | public Collection> searchClass(final Matcher> classMatcher) {
34 | final Set> classSet = new LinkedHashSet>();
35 | for (Class> clazz : classDataSource.allLoadedClasses()) {
36 | if (classMatcher.matching(clazz)) {
37 | classSet.add(clazz);
38 | }
39 | }
40 | return classSet;
41 | }
42 |
43 | @Override
44 | public Collection> searchSubClass(final Class> targetClass) {
45 | final Set> classSet = new LinkedHashSet>();
46 | for (Class> clazz : classDataSource.allLoadedClasses()) {
47 | if (!clazz.equals(targetClass)
48 | && targetClass.isAssignableFrom(clazz)) {
49 | classSet.add(clazz);
50 | }
51 | }
52 | return classSet;
53 | }
54 |
55 | @Override
56 | public Collection> searchClassWithSubClass(Matcher> classMatcher) {
57 | final Set> matchedClassSet = new LinkedHashSet>();
58 |
59 | // 搜索所有匹配器需求
60 | // 搜索当前匹配器所匹配的类
61 | for (Class> matchedClass : searchClass(classMatcher)) {
62 |
63 | // 首先添加自己
64 | matchedClassSet.add(matchedClass);
65 |
66 | if (!GlobalOptions.isDisableSubClass) {
67 | // 继续搜索子类
68 | matchedClassSet.addAll(searchSubClass(matchedClass));
69 | }
70 |
71 | }
72 | return matchedClassSet;
73 | }
74 |
75 |
76 | /**
77 | * 返回类中的所有可见方法
78 | * 所谓可见方法的定义是开发在类中可以直接通过Java语法继承关系感知到的方法
79 | *
80 | * @param clazz 目标类
81 | * @return 类的所有可见方法
82 | */
83 | private Set listVisualMethod(final Class> clazz) {
84 | final Set methodSet = new LinkedHashSet();
85 |
86 | // 首先查出当前类所声明的所有方法
87 | final Method[] classDeclaredMethodArray = clazz.getDeclaredMethods();
88 | if (null != classDeclaredMethodArray) {
89 | for (Method declaredMethod : classDeclaredMethodArray) {
90 | methodSet.add(declaredMethod);
91 | }
92 | }
93 |
94 | // 查出当前类所有的父类
95 | final Collection> superClassSet = recGetSuperClass(clazz);
96 |
97 | // 查出所有父类的可见方法
98 | for (Class> superClass : superClassSet) {
99 | final Method[] superClassDeclaredMethodArray = superClass.getDeclaredMethods();
100 | if (null != superClassDeclaredMethodArray) {
101 | for (Method superClassDeclaredMethod : superClassDeclaredMethodArray) {
102 |
103 | final int modifier = superClassDeclaredMethod.getModifiers();
104 |
105 | // 私有方法可以过滤掉
106 | if (Modifier.isPrivate(modifier)) {
107 | continue;
108 | }
109 |
110 | // public & protected 这两种情况是可以通过继承可见
111 | // 所以放行
112 | else if (Modifier.isPublic(modifier)
113 | || Modifier.isProtected(modifier)) {
114 | methodSet.add(superClassDeclaredMethod);
115 | }
116 |
117 | // 剩下的情况只剩下默认, 默认的范围需要同包才能生效
118 | else if (null != clazz
119 | && null != superClassDeclaredMethod
120 | && null != superClassDeclaredMethod.getDeclaringClass()
121 | && GaCheckUtils.isEquals(clazz.getPackage(), superClassDeclaredMethod.getDeclaringClass().getPackage())) {
122 | methodSet.add(superClassDeclaredMethod);
123 | }
124 |
125 | }
126 | }
127 | }
128 |
129 | return methodSet;
130 | }
131 |
132 | /*
133 | * 移除来自{@link java.lang.Object}的方法
134 | */
135 | private Collection removeObjectMethods(final Collection gaMethods) {
136 | final Iterator gaMethodIt = gaMethods.iterator();
137 | while (gaMethodIt.hasNext()) {
138 |
139 | final GaMethod gaMethod = gaMethodIt.next();
140 | if (GaCheckUtils.isEquals(gaMethod.getDeclaringClass(), Object.class)) {
141 | gaMethodIt.remove();
142 | }
143 |
144 | }
145 |
146 | return gaMethods;
147 | }
148 |
149 | @Override
150 | public Collection searchClassGaMethods(Class> targetClass, Matcher gaMethodMatcher) {
151 |
152 | final Set gaMethodSet = new LinkedHashSet();
153 |
154 | for (final Method method : listVisualMethod(targetClass)) {
155 | final GaMethod gaMethod = new GaMethod.MethodImpl(method);
156 | if (gaMethodMatcher.matching(gaMethod)) {
157 | gaMethodSet.add(gaMethod);
158 | }
159 | }
160 |
161 | // 因为构造函数不能继承,所以这里就不用像方法这么复杂的做可视化处理了
162 | for (final Constructor> constructor : targetClass.getDeclaredConstructors()) {
163 | final GaMethod gaMethod = new GaMethod.ConstructorImpl(constructor);
164 | if (gaMethodMatcher.matching(gaMethod)) {
165 | gaMethodSet.add(gaMethod);
166 | }
167 | }
168 |
169 | return removeObjectMethods(gaMethodSet);
170 | }
171 |
172 | }
173 |
--------------------------------------------------------------------------------
/core/src/main/resources/com/github/ompc/greys/core/res/javascript/greys-module.js:
--------------------------------------------------------------------------------
1 | /**
2 | * GREYS模块
3 | * function watching(listener)
4 | */
5 | define('greys', function () {
6 |
7 | // 监听器集合
8 | var _listeners = [];
9 |
10 | // 带匹配需求的监听器集合
11 | var _regex_listeners = [];
12 |
13 | /**
14 | * 数组forEach遍历
15 | * @param arr 数组
16 | * @param func 回调函数
17 | */
18 | function arrayForEach(arr, func) {
19 | for (var index = 0; index < arr.length; index++) {
20 | func(index, arr[index]);
21 | }
22 | }
23 |
24 | function watching() {
25 | // watching(listener)
26 | if (arguments.length == 1
27 | && arguments[0] instanceof Object) {
28 | _listeners.push(arguments[0]);
29 | }
30 |
31 | // watching(/class_name_regex/, listener)
32 | else if (arguments.length == 2
33 | && arguments[0] instanceof RegExp
34 | && arguments[1] instanceof Object) {
35 | watching(arguments[0], /.*/, arguments[1]);
36 | }
37 |
38 | // watching(/class_name_regex/, /method_name_regex/, listener)
39 | else if (arguments.length == 3
40 | && arguments[0] instanceof RegExp
41 | && arguments[1] instanceof RegExp
42 | && arguments[2] instanceof Object) {
43 | _regex_listeners.push({
44 | testClass: arguments[0],
45 | testMethod: arguments[1],
46 | listener: arguments[2]
47 | });
48 | }
49 | }
50 |
51 | return {
52 |
53 | /**
54 | * 添加监听器,凡是被js命令所拦截到的方法都会流入到注册的监听器中
55 | * watching(listener)
56 | * watching(/class_name_regex/,/method_name_regex/,listener)
57 | * watching(/class_name_regex/,listener)
58 | */
59 | watching: watching,
60 |
61 | testJavaClassName: function (javaClassName) {
62 | for (var index in _regex_listeners) {
63 | var _regex_listener = _regex_listeners[index];
64 | if (_regex_listener
65 | && _regex_listener.testClass.test(javaClassName)) {
66 | return true;
67 | }
68 | }//for
69 | return false;
70 | },
71 |
72 | testJavaMethodName: function (javaMethodName) {
73 | for (var index in _regex_listeners) {
74 | var _regex_listener = _regex_listeners[index];
75 | if (_regex_listener
76 | && _regex_listener.testMethod.test(javaMethodName)) {
77 | return true;
78 | }
79 | }//for
80 | return false;
81 | },
82 |
83 | create: function (output) {
84 | arrayForEach(_listeners, function (index, listener) {
85 | if (listener.create) {
86 | listener.create(output);
87 | }
88 | });
89 | arrayForEach(_regex_listeners, function (index, _regex_listener) {
90 | if (_regex_listener.listener.create) {
91 | _regex_listener.listener.create(output);
92 | }
93 | });
94 | },
95 |
96 | destroy: function (output) {
97 | arrayForEach(_listeners, function (index, listener) {
98 | if (listener.destroy) {
99 | listener.destroy(output);
100 | }
101 | });
102 | arrayForEach(_regex_listeners, function (index, _regex_listener) {
103 | if (_regex_listener.listener.destroy) {
104 | _regex_listener.listener.destroy(output);
105 | }
106 | });
107 | },
108 |
109 | before: function (output, advice, context) {
110 | arrayForEach(_listeners, function (index, listener) {
111 | if (listener.before) {
112 | listener.before(output, advice, context);
113 | }
114 | });
115 | arrayForEach(_regex_listeners, function (index, _regex_listener) {
116 | if (_regex_listener.listener.before) {
117 | _regex_listener.listener.before(output, advice, context);
118 | }
119 | });
120 | },
121 |
122 | returning: function (output, advice, context) {
123 | arrayForEach(_listeners, function (index, listener) {
124 | if (listener.returning) {
125 | listener.returning(output, advice, context);
126 | }
127 | });
128 | arrayForEach(_regex_listeners, function (index, _regex_listener) {
129 | if (_regex_listener.listener.returning) {
130 | _regex_listener.listener.returning(output, advice, context);
131 | }
132 | });
133 | },
134 |
135 | throwing: function (output, advice, context) {
136 | arrayForEach(_listeners, function (index, listener) {
137 | if (listener.throwing) {
138 | listener.throwing(output, advice, context);
139 | }
140 | });
141 | arrayForEach(_regex_listeners, function (index, _regex_listener) {
142 | if (_regex_listener.listener.throwing) {
143 | _regex_listener.listener.throwing(output, advice, context);
144 | }
145 | });
146 | },
147 |
148 | }
149 |
150 | })
151 |
152 | // 向全局对象注入GREYS回调函数
153 | require(['global', 'greys'], function (global, greys) {
154 | global.__greys_module_test_java_class_name = function (javaClassName) {
155 | return greys.testJavaClassName(javaClassName);
156 | }
157 | global.__greys_module_test_java_method_name = function (javaMethodName) {
158 | return greys.testJavaMethodName(javaMethodName);
159 | }
160 | global.__greys_module_create = function (output) {
161 | greys.create(output);
162 | }
163 | global.__greys_module_destroy = function (output) {
164 | greys.destroy(output);
165 | }
166 | global.__greys_module_before = function (output, advice, context) {
167 | greys.before(output, advice, context);
168 | }
169 | global.__greys_module_returning = function (output, advice, context) {
170 | greys.returning(output, advice, context);
171 | }
172 | global.__greys_module_throwing = function (output, advice, context) {
173 | greys.throwing(output, advice, context);
174 | }
175 | })
--------------------------------------------------------------------------------