In addition to JDK and cglib, are there three types of agency? Interview stuck again! "

Bugstack wormhole stack 2020-11-06 01:17:35
addition jdk cglib types agency


author : Little brother Fu
Blog :https://bugstack.cn

precipitation 、 Share 、 grow up , Let yourself and others have something to gain !

One 、 Preface

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

Two 、 Interview questions

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 !

3、 ... and 、 Five types of agency

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 .

0. First, add a little knowledge of reflection

@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);
}

  • Index :
  • comment : Where there's a proxy, there's almost a reflection , They are a set of functional classes that work together . Methods can be called in reflection 、 get attribute 、 Get the notes, and so on . These can be combined with the following class proxy , Complete the technical scenarios in various frameworks .

1. JDK Agency mode

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
*/

  • Index :
  • scene : Middleware development 、 The application of agent pattern and decorator pattern in design pattern
  • comment : such JDK The built-in class proxy is a very common one , It's also a very simple one . You can see it in some middleware code, such as : Database routing component 、Redis Components etc. , At the same time, we can also apply it to design patterns in this way .

2. CGLIB Agency mode

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
*/

  • Index :
  • scene :Spring、AOP section 、 Authentication services 、 Middleware development 、RPC Frame, etc
  • comment :CGLIB differ JDK, Its underlying use ASM Bytecode framework modifies the script implementation agent in a class , So this kind of agency doesn't need to be like JDK That requires an interface to proxy . At the same time, thanks to the use of bytecode framework , So this kind of proxy is better than using JDK The way of agency is fast 1.5~2.0 times .

3. ASM Agency mode

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
*/

  • Index :
  • scene : Full link monitoring 、 Crack toolkit 、CGLIB、Spring Get class metadata, etc
  • comment : This kind of proxy is to use bytecode programming for processing , Its implementation is relatively complex , And you need to understand Java Knowledge of virtual machine specification . Because every step of your proxy operation , They're all manipulating bytecode instructions , for example :Opcodes.GETSTATICOpcodes.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 .

4. Byte-Buddy Agency mode

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
*/

  • Index :
  • scene :AOP section 、 Class agent 、 Components 、 monitor 、 journal
  • comment :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 .

5. Javassist Agency mode

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
*/

  • Index :
  • scene : Full link monitoring 、 Class agent 、AOP
  • comment :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 .

Four 、 summary

  • The actual purpose of agency is through some technical means , Replace the original implementation class or inject new bytecode instructions into the original implementation class . And these technologies will eventually use some framework applications 、 Middleware development and similar non-invasive full link monitoring .
  • A deep study of technology stack can let you thoroughly understand some basic fundamental principles , Through this kind of study, we can get rid of some vague questions , Also can let oneself have better job opportunity and salary through the development of this kind of Technology .
  • These technologies are not easy to learn , There may even be some brain burn . But every piece of technology worth learning can help you break through the technical bottleneck at a certain stage .

5、 ... and 、 Series recommendation

( Please indicate the author and source of this article WeChat official account :bugstack Wormhole stack | author : Little brother Fu

Show Disqus Comments
版权声明
本文为[Bugstack wormhole stack]所创,转载请带上原文链接,感谢

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云