author : Little brother Fu
Blog :https://bugstack.cn
precipitation 、 Share 、 grow up , Let yourself and others have something to gain !
Programming learning , The width or the depth of digging first ?
In fact, the width and depth of technology complement each other , How much technology you can learn is related to the depth of your understanding of a technology , And how deep you can explore a technology requires you to have a certain breadth of cognition . Otherwise, if you just want to understand the skin or knock a piece of code , The harvest is not necessarily big , Or it costs a lot .
Technical bottlenecks , Age related or big factory ?
I've been an interviewer for a long time , I've interviewed a lot of people . Sometimes you don't have to be old enough to be skilled , It doesn't have to be just working 2 It's not going to work for about a year . Often we say some interviews make rockets , But in the answers of these job seekers , Can give very accurate answers . That is, he can answer to the point , This is what you can do with understanding .
Working hours and whether in a large factory , These are the amount of resources that can be accessed , See the height of technical insight . But I really want to absorb these things to myself , Still need individual struggle . Otherwise, a lot of things will be put in front of you , It's hard for you to see . Most of the time you can see it's just the title
Thank you plane , Notes
,10.1 Holiday play hi plane , Seems to have set their own learning goals before the holiday ! But the thought of another interview , I can't help cramming , I started reading brother Fu's blog :bugstack.cn
interviewer : The plane , Look at you flustered ?
Thank you plane : No, , No, , I'm afraid I didn't have time to run upstairs .
interviewer : good ! I don't think your resume has been updated , Let's talk about dynamic proxy and reflection this time , Do you know how to proxy a class ?
Thank you plane : I know that , Use JDK Own class Proxy
You can delegate a class , You can also use CGLIB agent .
interviewer : Um. , What's the difference between the two agents ?
Thank you plane : Like one is JDK Need to have an interface ,CGLIB You don't need to .
interviewer : Why? ?
Thank you plane : Why? ? this …
interviewer : When you develop it yourself , Do you do any business with an agent ?
Thank you plane :… It doesn't seem that !
The plane can only slip home , Lack of technical depth , And it hasn't been used in practice , There is still a lot to be done !
No accident
, You may only know two types of agency . One is JDK Self contained , The other is CGLIB.
We first define an interface and the corresponding implementation class , It is convenient for subsequent use of proxy classes to add output information in methods .
Defining interfaces
public interface IUserApi {
String queryUserInfo();
}
Implementation interface
public class UserApi implements IUserApi {
public String queryUserInfo() {
return " Little brother Fu , official account :bugstack Wormhole stack | precipitation 、 Share 、 grow up , Let yourself and others have something to gain !";
}
}
good ! Next, we'll add a line of extra output information to the class method using the proxy .
@Test
public void test_reflect() throws Exception {
Class<UserApi> clazz = UserApi.class;
Method queryUserInfo = clazz.getMethod("queryUserInfo");
Object invoke = queryUserInfo.invoke(clazz.newInstance());
System.out.println(invoke);
}
public class JDKProxy {
public static <T> T getProxy(Class clazz) throws Exception {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
return (T) Proxy.newProxyInstance(classLoader, new Class[]{clazz}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + " You have been represented ,By JDKProxy!");
return " Little brother Fu , official account :bugstack Wormhole stack | precipitation 、 Share 、 grow up , Let yourself and others have something to gain !";
}
});
}
}
@Test
public void test_JDKProxy() throws Exception {
IUserApi userApi = JDKProxy.getProxy(IUserApi.class);
String invoke = userApi.queryUserInfo();
logger.info(" test result :{}", invoke);
}
/**
* test result :
*
* queryUserInfo You have been represented ,By JDKProxy!
* 19:55:47.319 [main] INFO org.itstack.interview.test.ApiTest - test result : Little brother Fu , official account :bugstack Wormhole stack | precipitation 、 Share 、 grow up , Let yourself and others have something to gain !
*
* Process finished with exit code 0
*/
public class CglibProxy implements MethodInterceptor {
public Object newInstall(Object object) {
return Enhancer.create(object.getClass(), this);
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(" I was CglibProxy Agent ");
return methodProxy.invokeSuper(o, objects);
}
}
@Test
public void test_CglibProxy() throws Exception {
CglibProxy cglibProxy = new CglibProxy();
UserApi userApi = (UserApi) cglibProxy.newInstall(new UserApi());
String invoke = userApi.queryUserInfo();
logger.info(" test result :{}", invoke);
}
/**
* test result :
*
* queryUserInfo You have been represented ,By CglibProxy!
* 19:55:47.319 [main] INFO org.itstack.interview.test.ApiTest - test result : Little brother Fu , official account :bugstack Wormhole stack | precipitation 、 Share 、 grow up , Let yourself and others have something to gain !
*
* Process finished with exit code 0
*/
public class ASMProxy extends ClassLoader {
public static <T> T getProxy(Class clazz) throws Exception {
ClassReader classReader = new ClassReader(clazz.getName());
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
classReader.accept(new ClassVisitor(ASM5, classWriter) {
@Override
public MethodVisitor visitMethod(int access, final String name, String descriptor, String signature, String[] exceptions) {
// Method filtration
if (!"queryUserInfo".equals(name))
return super.visitMethod(access, name, descriptor, signature, exceptions);
final MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
return new AdviceAdapter(ASM5, methodVisitor, access, name, descriptor) {
@Override
protected void onMethodEnter() {
// Execution instruction ; Get static properties
methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
// Load constant load constant
methodVisitor.visitLdcInsn(name + " You have been represented ,By ASM!");
// Calling method
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
super.onMethodEnter();
}
};
}
}, ClassReader.EXPAND_FRAMES);
byte[] bytes = classWriter.toByteArray();
return (T) new ASMProxy().defineClass(clazz.getName(), bytes, 0, bytes.length).newInstance();
}
}
@Test
public void test_ASMProxy() throws Exception {
IUserApi userApi = ASMProxy.getProxy(UserApi.class);
String invoke = userApi.queryUserInfo();
logger.info(" test result :{}", invoke);
}
/**
* test result :
*
* queryUserInfo You have been represented ,By ASM!
* 20:12:26.791 [main] INFO org.itstack.interview.test.ApiTest - test result : Little brother Fu , official account :bugstack Wormhole stack | precipitation 、 Share 、 grow up , Let yourself and others have something to gain !
*
* Process finished with exit code 0
*/
Opcodes.GETSTATIC
、Opcodes.INVOKEVIRTUAL
, In addition to these, there are small 200 A common command . But this is the closest way to the bottom , It's also the fastest way . So in some full link monitoring using bytecode instrumentation , It's very common .public class ByteBuddyProxy {
public static <T> T getProxy(Class clazz) throws Exception {
DynamicType.Unloaded<?> dynamicType = new ByteBuddy()
.subclass(clazz)
.method(ElementMatchers.<MethodDescription>named("queryUserInfo"))
.intercept(MethodDelegation.to(InvocationHandler.class))
.make();
return (T) dynamicType.load(Thread.currentThread().getContextClassLoader()).getLoaded().newInstance();
}
}
@RuntimeType
public static Object intercept(@Origin Method method, @AllArguments Object[] args, @SuperCall Callable<?> callable) throws Exception {
System.out.println(method.getName() + " You have been represented ,By Byte-Buddy!");
return callable.call();
}
@Test
public void test_ByteBuddyProxy() throws Exception {
IUserApi userApi = ByteBuddyProxy.getProxy(UserApi.class);
String invoke = userApi.queryUserInfo();
logger.info(" test result :{}", invoke);
}
/**
* test result :
*
* queryUserInfo You have been represented ,By Byte-Buddy!
* 20:19:44.498 [main] INFO org.itstack.interview.test.ApiTest - test result : Little brother Fu , official account :bugstack Wormhole stack | precipitation 、 Share 、 grow up , Let yourself and others have something to gain !
*
* Process finished with exit code 0
*/
Byte Buddy
It is also a bytecode operation class library , but Byte Buddy
It's easier to use . No need to understand bytecode instructions , You can use the simple API It's easy to manipulate bytecode , Control classes and methods . Compared with JDK A dynamic proxy 、cglib,Byte Buddy It has some advantages in performance . in addition ,2015 year 10 month ,Byte Buddy By Oracle Granted Duke’s Choice Awards . The award is for Byte Buddy Of “ Java Great innovation in technology ” Express appreciation for .public class JavassistProxy extends ClassLoader {
public static <T> T getProxy(Class clazz) throws Exception {
ClassPool pool = ClassPool.getDefault();
// Get class
CtClass ctClass = pool.get(clazz.getName());
// Access method
CtMethod ctMethod = ctClass.getDeclaredMethod("queryUserInfo");
// Pre method strengthening
ctMethod.insertBefore("{System.out.println(\"" + ctMethod.getName() + " You have been represented ,By Javassist\");}");
byte[] bytes = ctClass.toBytecode();
return (T) new JavassistProxy().defineClass(clazz.getName(), bytes, 0, bytes.length).newInstance();
}
}
@Test
public void test_JavassistProxy() throws Exception {
IUserApi userApi = JavassistProxy.getProxy(UserApi.class)
String invoke = userApi.queryUserInfo();
logger.info(" test result :{}", invoke);
}
/**
* test result :
*
* queryUserInfo You have been represented ,By Javassist
* 20:23:39.139 [main] INFO org.itstack.interview.test.ApiTest - test result : Little brother Fu , official account :bugstack Wormhole stack | precipitation 、 Share 、 grow up , Let yourself and others have something to gain !
*
* Process finished with exit code 0
*/
Javassist
Is a very widely used bytecode instrumentation framework , Almost a majority of non intrusive full link monitoring will choose to use this framework . Because it doesn't want to ASM Operating bytecode that way leads to risk , At the same time, its functions are very complete . in addition , This framework can write instrumentation code directly in the way it provides , You can also use bytecode instructions to control the generation of code , So overall, it's a very good bytecode framework .( Please indicate the author and source of this article WeChat official account :bugstack Wormhole stack | author : Little brother Fu )