Skip to content

Commit 4756479

Browse files
author
Xiang Zhong
committed
First Attempt Migrating CGLIB to ByteBuddy
1 parent f26fd0a commit 4756479

File tree

3 files changed

+110
-58
lines changed

3 files changed

+110
-58
lines changed

ipp-v3-java-devkit/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,12 @@
119119
<artifactId>jmockit</artifactId>
120120
<version>1.25</version>
121121
<scope>test</scope>
122-
</dependency>
122+
</dependency>
123+
<dependency>
124+
<groupId>net.bytebuddy</groupId>
125+
<artifactId>byte-buddy</artifactId>
126+
<version>1.12.10</version>
127+
</dependency>
123128
</dependencies>
124129
<build>
125130
<testResources>

ipp-v3-java-devkit/src/main/java/com/intuit/ipp/query/GenerateQuery.java

Lines changed: 87 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
import java.util.Calendar;
2020
import java.util.Date;
2121

22+
import net.bytebuddy.ByteBuddy;
23+
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
24+
import net.bytebuddy.implementation.MethodDelegation;
25+
import net.bytebuddy.implementation.SuperMethodCall;
26+
import net.bytebuddy.matcher.ElementMatchers;
2227
import net.sf.cglib.proxy.Callback;
2328
import net.sf.cglib.proxy.CallbackFilter;
2429
import net.sf.cglib.proxy.Enhancer;
@@ -34,25 +39,25 @@
3439

3540
/**
3641
* Class used to generate the query string
37-
*
42+
*
3843
*/
3944
public final class GenerateQuery {
4045

4146
/**
4247
* logger instance
4348
*/
4449
private static final org.slf4j.Logger LOG = Logger.getLogger();
45-
50+
4651
/**
4752
* variable LEN_3
4853
*/
4954
private static final int LEN_3 = 3;
50-
55+
5156
/**
5257
* variable path
5358
*/
5459
public static ThreadLocal<Path<?>> path = new ThreadLocal<Path<?>>();
55-
60+
5661
/**
5762
* varriable message
5863
*/
@@ -64,53 +69,94 @@ public final class GenerateQuery {
6469
private GenerateQuery() {
6570
}
6671

67-
/**
68-
* Method to create the query entity for the given class
69-
*
70-
* @param cl the class
71-
* @return the proxified object
72-
*/
72+
// /**
73+
// * Method to create the query entity for the given class
74+
// *
75+
// * @param cl the class
76+
// * @return the proxified object
77+
// */
78+
// @SuppressWarnings("unchecked")
79+
// public static <T> T createQueryEntity(Class<T> cl) {
80+
// Enhancer enhancer = new Enhancer();
81+
// if (cl.isInterface()) {
82+
// LOG.debug("The given class is interface");
83+
// //enhancer.setInterfaces(new Class[] { cl });
84+
// //enhancer.setCallback(new MyMethodInterceptor());
85+
// } else {
86+
// enhancer.setSuperclass(cl);
87+
// }
88+
// enhancer.setCallbackFilter(CALLBACK_FILTER);
89+
// enhancer.setCallbacks(new Callback[] {NoOp.INSTANCE, new MyMethodInterceptor()});
90+
// return (T) enhancer.create();
91+
// }
92+
//
93+
// /**
94+
// * Method to create the query for the given entity
95+
// *
96+
// * @param entity the entity
97+
// * @return the proxified object
98+
// */
99+
// @SuppressWarnings("unchecked")
100+
// public static <T> T createQueryEntity(T entity) {
101+
// Class<?> cl = entity.getClass();
102+
// Enhancer enhancer = new Enhancer();
103+
// if (cl.isInterface()) {
104+
// LOG.debug("The given entity is interface");
105+
// //enhancer.setInterfaces(new Class[] { cl });
106+
// //enhancer.setCallback(new MyMethodInterceptor());
107+
// } else {
108+
// enhancer.setSuperclass(cl);
109+
// enhancer.setCallbackFilter(CALLBACK_FILTER);
110+
// enhancer.setCallbacks(new Callback[] {NoOp.INSTANCE, new MyMethodInterceptor()});
111+
// }
112+
// return (T) enhancer.create();
113+
// }
114+
115+
73116
@SuppressWarnings("unchecked")
74117
public static <T> T createQueryEntity(Class<T> cl) {
75-
Enhancer enhancer = new Enhancer();
118+
Class<?> proxied = null;
76119
if (cl.isInterface()) {
77120
LOG.debug("The given class is interface");
78-
//enhancer.setInterfaces(new Class[] { cl });
79-
//enhancer.setCallback(new MyMethodInterceptor());
80121
} else {
81-
enhancer.setSuperclass(cl);
122+
proxied = new ByteBuddy()
123+
.subclass(cl)
124+
.method(ElementMatchers.any())
125+
.intercept(MethodDelegation.to(new MyMethodInterceptor()))
126+
.method(ElementMatchers.isClone().or(ElementMatchers.isFinalizer()).or(ElementMatchers.isEquals()).or(ElementMatchers.isHashCode()).or(ElementMatchers.isToString()))
127+
.intercept(SuperMethodCall.INSTANCE)
128+
.make()
129+
.load(cl.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
130+
.getLoaded();
82131
}
83-
enhancer.setCallbackFilter(CALLBACK_FILTER);
84-
enhancer.setCallbacks(new Callback[] {NoOp.INSTANCE, new MyMethodInterceptor()});
85-
return (T) enhancer.create();
132+
return (T) proxied;
86133
}
87134

88-
/**
89-
* Method to create the query for the given entity
90-
*
91-
* @param entity the entity
92-
* @return the proxified object
93-
*/
94135
@SuppressWarnings("unchecked")
95136
public static <T> T createQueryEntity(T entity) {
96137
Class<?> cl = entity.getClass();
97-
Enhancer enhancer = new Enhancer();
138+
Class<?> proxied = null;
98139
if (cl.isInterface()) {
99140
LOG.debug("The given entity is interface");
100-
//enhancer.setInterfaces(new Class[] { cl });
101-
//enhancer.setCallback(new MyMethodInterceptor());
102141
} else {
103-
enhancer.setSuperclass(cl);
104-
enhancer.setCallbackFilter(CALLBACK_FILTER);
105-
enhancer.setCallbacks(new Callback[] {NoOp.INSTANCE, new MyMethodInterceptor()});
142+
proxied = new ByteBuddy()
143+
.subclass(cl)
144+
.method(ElementMatchers.any())
145+
.intercept(MethodDelegation.to(new MyMethodInterceptor()))
146+
.method(ElementMatchers.isClone().or(ElementMatchers.isFinalizer()).or(ElementMatchers.isEquals()).or(ElementMatchers.isHashCode()).or(ElementMatchers.isToString()))
147+
.intercept(SuperMethodCall.INSTANCE)
148+
.make()
149+
.load(cl.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
150+
.getLoaded();
106151
}
107-
return (T) enhancer.create();
152+
return (T) proxied;
108153
}
109154

155+
110156
/**
111157
* when no handler for specific return type is defined which means properties of that type cannot be inserted in filter expression but can be
112158
* listed in select part, it will return Path
113-
*
159+
*
114160
* @param ret the object
115161
* @return path the path
116162
*/
@@ -129,7 +175,7 @@ public static <T> T createQueryEntity(T entity) {
129175
/**
130176
* When return type is Calendar, it will create CalendarPath which will expose filter methods accepting java.util.Calendar, java.util.Date and
131177
* java.sql.Date
132-
*
178+
*
133179
* @param ret
134180
* @return
135181
*/
@@ -141,7 +187,7 @@ public static <T> T createQueryEntity(T entity) {
141187

142188
/**
143189
* Method to get the calendar path
144-
*
190+
*
145191
* @param ret the date
146192
* @return CalendarPath the calendar path
147193
*/
@@ -153,7 +199,7 @@ public static <T> T createQueryEntity(T entity) {
153199

154200
/**
155201
* When return type is String, it will create StringPath which will expose filter methods accepting only String
156-
*
202+
*
157203
* @param ret the string
158204
* @return StringPath the string path
159205
*/
@@ -165,7 +211,7 @@ public static <T> T createQueryEntity(T entity) {
165211

166212
/**
167213
* Method to get the number path
168-
*
214+
*
169215
* @param ret the number
170216
* @return NumberPath the number path
171217
*/
@@ -177,7 +223,7 @@ public static <T> T createQueryEntity(T entity) {
177223

178224
/**
179225
* Method to get the boolean path
180-
*
226+
*
181227
* @param ret the boolean
182228
* @return BooleanPath the boolean path
183229
*/
@@ -189,7 +235,7 @@ public static <T> T createQueryEntity(T entity) {
189235

190236
/**
191237
* Method to get the Enum path
192-
*
238+
*
193239
* @param ret the enum
194240
* @return EnumPath the enum path
195241
*/
@@ -201,7 +247,7 @@ public static <T> T createQueryEntity(T entity) {
201247

202248
/**
203249
* Method to get the optional syntax
204-
*
250+
*
205251
* @param path the path
206252
* @param pathlist the path list
207253
* @return OptionalSyntax the optional syntax
@@ -222,7 +268,7 @@ public static <T extends IEntity> OptionalSyntax select(Path<?> path, Path<?>...
222268

223269
/**
224270
* Method to get the optional syntax for the given entity
225-
*
271+
*
226272
* @param entity the entity
227273
* @return OptionalSyntax the optional syntax
228274
*/
@@ -240,7 +286,7 @@ public static <T extends IEntity> OptionalSyntax selectCount(T entity) {
240286

241287
/**
242288
* Method to get the query message
243-
*
289+
*
244290
* @return QueryMessage the query message
245291
*/
246292
public static QueryMessage getMessage() {
@@ -249,7 +295,7 @@ public static QueryMessage getMessage() {
249295

250296
/**
251297
* Method to set the query message
252-
*
298+
*
253299
* @param mess the query message
254300
*/
255301
public static void setMessage(QueryMessage mess) {

ipp-v3-java-devkit/src/main/java/com/intuit/ipp/query/MyMethodInterceptor.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,41 +28,42 @@
2828
import com.intuit.ipp.exception.FMSException;
2929
import com.intuit.ipp.util.Logger;
3030

31+
import net.bytebuddy.implementation.bind.annotation.*;
3132
import net.sf.cglib.proxy.MethodInterceptor;
3233
import net.sf.cglib.proxy.MethodProxy;
3334

3435
/**
3536
* For intercepting method and adding the name of method called in threadlocal stringbuilder.
36-
*
37+
*
3738
* @author lokeshg
38-
*
39+
*
3940
*/
40-
public class MyMethodInterceptor implements MethodInterceptor {
41+
public class MyMethodInterceptor {
4142

4243
/**
4344
* logger instance
4445
*/
4546
private static final org.slf4j.Logger LOG = Logger.getLogger();
46-
47+
4748
/**
4849
* variable NUM_3
4950
*/
5051
private static final int NUM_3 = 3;
51-
52+
5253
/**
5354
* variable NUM_2
5455
*/
5556
private static final int NUM_2 = 2;
56-
57+
5758
/**
5859
* Constructor MyMethodInterceptor
59-
*
60+
*
6061
*/
6162
public MyMethodInterceptor() {
6263
}
6364

64-
@Override
65-
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws FMSException {
65+
@RuntimeType
66+
public Object intercept(@This Object arg0, @Origin Method arg1, @AllArguments Object[] arg2, @SuperMethod Method arg3) throws FMSException {
6667

6768
if (GenerateQuery.path.get() == null) {
6869
GenerateQuery.path.set(new Path<Object>(extractPropertyName(arg1), extractEntity(arg0)));
@@ -89,7 +90,7 @@ private String extractEntity(Object obj) {
8990

9091
/**
9192
* extract the name of property from method called.
92-
*
93+
*
9394
* @param method
9495
* @return
9596
*/
@@ -101,13 +102,13 @@ protected String extractPropertyName(Method method) {
101102

102103
/**
103104
* create the object for linked method call or object of leaf node
104-
*
105+
*
105106
* @param type
106107
* @return
107-
* @throws Throwable
108+
* @throws Throwable
108109
*/
109110
@SuppressWarnings("unchecked")
110-
public <T> T createInstance(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3)
111+
public <T> T createInstance(Object arg0, Method arg1, Object[] arg2, Method arg3)
111112
throws FMSException {
112113
Object obj = null;
113114
Class<?> type = arg1.getReturnType();
@@ -144,7 +145,7 @@ public <T> T createInstance(Object arg0, Method arg1, Object[] arg2, MethodProxy
144145
Type t = arg1.getGenericReturnType();
145146
Object value = getObject(t);
146147
Object queryValue = GenerateQuery.createQueryEntity(value);
147-
obj = arg3.invokeSuper(arg0, arg2);
148+
obj = arg3.invoke(arg0, arg2);
148149
((List<Object>) obj).add(queryValue);
149150
} catch (Throwable t) {
150151
throw new FMSException(t);
@@ -165,7 +166,7 @@ public <T> T createInstance(Object arg0, Method arg1, Object[] arg2, MethodProxy
165166

166167
/**
167168
* Method to get the object for the given type
168-
*
169+
*
169170
* @param type the type
170171
* @return Object the object
171172
* @throws Throwable
@@ -182,5 +183,5 @@ public Object getObject(Type type) throws FMSException {
182183
}
183184
}
184185
return obj;
185-
}
186+
}
186187
}

0 commit comments

Comments
 (0)