We are all in the gutter, but some of us are looking at the stars.– Oscar Wilde

I. Definition of agent

Now that agency is mentioned, where is it embodied in the end? If I’m talking about static proxies, what is static? When we say dynamic proxy, we say exactly where is the dynamic? Also in dynamic proxies, why does the JDK dynamic proxy have to be an implementation interface, but the Cglib dynamic proxy does not?

Appeared a lot of times, the program bugs, we all like to see the source code, from the Angle of the source code parsing, the cause of the problem it is a good habit, but to express to the product manager, said in the source code is written, so the source was a good thing, only to become the Dui tools, don’t say a product manager heard source two characters have a headache, Over time, programmers lose touch with the original idea and lose the fun of coding in the first place.

In the final analysis, between the source code and product manager, we programmers also want to do a good job of agent, in plain English to convey the source code thinking, engineering thinking and product thinking collision, promote the development of business.

Agency is a verb. In the dictionary, it means to be entrusted by a party to exercise certain rights and do certain things on behalf of the party, such as signing a contract, litigation, etc. In fact, it is to help people do things.

In history, the most famous proxy was to listen to state affairs from behind a curtain, with the emperor sitting in front and the empress sitting behind, separated by a curtain, and the emperor learned to speak whatever the empress mother said. Sounds like a lot of trouble. I might as well pull back the curtain and call myself emperor.

Empress Wu Zetian did so in history, the result was against the “three cardinal guides wuchang” by posterity controversy, the queen of Britain does not have this “husband for wife” rules, not when the good. In the Qing Dynasty, the Empress Dowager Cixi held the REINS of power. She did not want to delegate power or cause controversy, so she conducted a “curtain administration”. In fact, it made no difference who was up and who was down, as long as the people could live a good life.

1.1 Agents in reality

In our real life, agents are everywhere, such as ticket sellers, star agents, lawyers, etc. Before specifically launching agents, we should clarify the relationship between agents and intermediaries. At a glance, it seems that there is no difference. No, the agent emphasizes the replacement of the individual, while the intermediary emphasizes the transmission of information. For example, lawyers fight in court on behalf of clients, and real estate agents match the housing information to buyers.

For the client who needs to fight a lawsuit, the lawyer is the strengthened version of himself, not only has his own lawsuit requirements, but also professional legal knowledge and excellent eloquence, to help such a person to fight a lawsuit, to have a chance of success.

The real estate agent is doing poor information business, the seller does not know who is buying the house, the buyer does not know who is selling the house, the agent says I know, listen to me. This is called the middleman making the difference. Recently Xie Na Zhang Jie couple to buy a jump list on the hot search, jump list is over the intermediary directly to find the landlord to sign a contract, the intermediary boy full of grievances to do a good man.

In the Internet era, absolute information difference no longer exists, and it has been upgraded from a single fight to a platform, such as a certain Treasure in the field of e-commerce and a certain chain in the field of real estate.

1.2 Agents in coding

Anyway, what is a proxy in the coding world?

In the figure, the proxy class represents the entity class, and the entity class and the proxy class have a common interface. The reason for this design is that the proxy cannot be separated from the entity, there must be a relationship between them, that is, the proxy serves the entity. If the specific needs of the entity are not known, the proxy will be lonely.

The common abstract interface as agents and a contract between the entity, the contract stipulates that the agent need those behaviors of entity service, agent to get the contract will know what to do for entities, and according to the “to do”, the agent has a strong professional, surrounding the “what” to do some extra work, this process is enhanced.

The agent becomes an upgraded entity. The physical power has been extended. Direct contact with the agent is equivalent to indirect contact with the entity. And, of course, customers can also direct contact with the entity, thus increasing the complexity, for example, a company has r&d department and sales department, customer requirements can be directly to find research and development department to do, but r&d department will research and development, the price of the product, the service is not too to understand, this will waste a lot of time on the consequences of the research and development on stalling, the professional person to do professional, Leaving the rest to the agent is a more reasonable allocation.

Static proxy

2.1 Static Proxy Case

Wang Lee-hom has filed 11 pieces of evidence in a US court in a bid to secure visitation rights for his children in a high-profile divorce case. Li Lianglei submitted seven pieces of evidence in response to the court. In this process, Wang lee-hom will definitely hire a professional lawyer to take charge of the case. The entity is Wang Leehom and the agent is a lawyer. Mr. Wang hired lawyers to sign cooperation contracts that required them to win visitation rights for his children.

The SeeChildSuit interface specifies the claims of Wang and his lawyer

public interface SeeChildSuit {
    public void seeChild();
}
Copy the code

The Wanglihong class specifies the specific content of the lawsuit, which is to see the child

Public class Wanglihong implements SeeChildSuit {@override public void seeChild() {system.out.println (" want to see a child "); }}Copy the code

The Lawer class implemented the SeeChildSuit interface and used its own legal knowledge and professional skills to help Wang get visitation rights according to the contents of the contract. Lawyers need to prepare evidence, submit it to the court, state the claim, and argue the case in court according to the evidence needs. All this extra work is done by lawyers.

public class Lawer implements SeeChildSuit { SeeChildSuit seeChildSuit; public Lawer(SeeChildSuit seeChildSuit) { this.seeChildSuit = seeChildSuit; } @override public void seeChild() {system.out.println (" attorney prepares the evidence and states the claim: "); seeChildSuit.seeChild(); System.out.println(" Lawyers argue in court "); }}Copy the code

Open a court session to hear a

Public class TestCase {public static void main(String[] args) {system.out.println (" court "); public static void main(String[] args) {system.out.println (" court "); SeeChildSuit seeChildSuit = new Lawer(new Wanglihong()); seeChildSuit.seeChild(); }}Copy the code

Results:

It can be seen that the lawyer handled the case on behalf of Wang Leehom, and made full preparations for the victory of the case by virtue of his years of work experience and professional quality. I wish him to see his children soon. The above proxy is the static proxy process, its static means that the proxy class has been determined before the code execution, enhance the code and the generation of proxy class coupled together, any changes later, modify the proxy class on the line.

At this point, it seems perfect that Wang has appointed Bonnie E. Rabin, a 35-year veteran lawyer specializing in marriage and family law. The lawyer has extensive experience in dealing with complex financial problems.

If Bonnie’s lawyer gets stuck in a traffic jam on the day of the trial, the other lawyers won’t be able to take over the case for a while.

In competitive sports, starters and substitutes, starters are some star players, they have a spectacular achievements in the past, but this does not guarantee that every game to win, it has a great relationship and improvisation, therefore a game state good substitute for a bad player can still win the game.

The safest option for Wang is to hire a team of lawyers, with Bonnie as the starter and other lawyers as backup. It doesn’t matter which lawyer gets on the court, all that matters is winning.

Dynamic proxy is to realize the above idea, dynamic proxy agent to generate and enhance code separation, the so-called agent, at the end of the day is to give the original method enhancements, enhance code is like a key evidence in a lawsuit, wins the core is the key of evidence in the court, and which lawyer, this also conforms to the actual, the law is the evidence.

The purpose of a proxy is to construct an object that has the same behavior as the proxied object.

JDK dynamic proxies make proxying and proxied classes behave the same way by implementing the same interface.

2.2 Disadvantages of static proxies

Original agency not only holding entity class methods, and enhance the method, this will be coupled together, in the static agent, the goals of the agent in the proxy class method write enhancement method, this will cause the current proxy class is highly coupled entity class, seems like the entity class personal customization, then other entity class will not be able to reuse the proxy class, The proxy classes for this entity class can only be highly customized in the same way, if 1000 entity classes need proxies, then 1000 proxy classes need to be customized.

If you separate the proxy class from the enhancement method, you can reuse the proxy class, only changing the implementation of the enhancement method, so that no matter how the enhancement method changes, the proxy class does not change, and the change is transferred to the enhancement method. The specific implementation of the enhancement method is adjusted according to the specific business content, and the specific problem is analyzed. This flexible way to solve the problem is dynamic proxy.

Dynamic proxy

3.1 JDK Dynamic Proxy?

A static proxy is static because the proxy class needs to be written by the programmer before the program runs, whereas a dynamic proxy class does not need to be written by the programmer and is automatically generated at run time.

Then automatically generated proxy only purpose is to obtain the proxy class instances, this section does not involve the use of specific business, of course can be response in the underlying implementation, but also is involved in specific business agent enhanced code, requires the programmer to implement, the enhancement code in is the proxy class and proxy call, This enables both the proxy instance and the ability to configure the enhanced code as needed.

We’ve talked a lot about enhanced code, but how exactly should we implement it in dynamic proxies? This class implements the InvocationHandler interface. It also holds the propped object. Inside the InvocationHandler is an Invoke method that takes the propped object. Reflection allows methods in the proxied to be executed. Some enhancement code can be written before and after executing a method on a propped object through reflection.

This is a bit like surround notification in SpringAOP. In fact, in SpringAOP, the surround notification method is enhanced.

public class LawerInvocationHandler<T> implements InvocationHandler { @Override public Object invoke(Object proxy, Method, Object[] args) throws Throwable {system.out.println (" The lawyer prepares the evidence and states the claim: "); Object result = method.invoke(target, args); System.out.println(" Lawyers argue in court "); return result; }}Copy the code

3.1.1 case

Public interface

public interface SeeChildSuit {
    public void seeChild();
}
Copy the code

Proxied object

public class LawerInvocationHandler<T> implements InvocationHandler { T target; public LawerInvocationHandler(T target) { this.target = target; } /** * proxy: represents the dynamic proxy object * method: represents the executing method * args: */ @override public Object invoke(Object proxy, Method Method, Object[] args) throws Throwable {system.out.println (" Counsel prepares evidence and states the claim: "); Object result = method.invoke(target, args); System.out.println(" Lawyers argue in court "); return result; }}Copy the code

Test as a proxy object, and then call the target method

Public class TestCase {public static void main(String[] args) {system.out.println (" court "); public static void main(String[] args) {system.out.println (" court "); // Get the enhanced class InvocationHandler lawerHandler = new LawerInvocationHandler<SeeChildSuit>(new Wanglihong()); // Pass in the proxy class loader, proxy class interface, and enhancement class, Get the Proxy class SeeChildSuit seeChildSuitProxy = (SeeChildSuit) Proxy. NewProxyInstance (SeeChildSuit. Class. GetClassLoader (), new Class<? >[]{SeeChildSuit.class}, lawerHandler); / / using the proxy class implement the target method seeChildSuitProxy. SeeChild (); }}Copy the code

3.1.2 JDK Dynamic Proxy Mechanism

Now that I’ve prepared the enhanced code and the invocation of the target method of the proxying class, the Invoke method in InvocationHandler, where will the Invoke method be used?

Actually, working backward from the results we can see, we finally won a proxy object, call the proxy class method through a proxy object, by the method of the proxy class must exist in the proxy class, thus concluded that the proxy class and proxy classes have the same way, in the previous programming experience, or the two class implements the interface to obtain the same way, Either way, the two classes are related.

This same method is fully implemented in the proxy class. In the proxy class, we also need to find a way to get the complete implementation of the proxy class. So how does the proxy class get the complete implementation of the proxy class method? Let’s dig into the code to find the answer to this question.

This is the code that generates the Proxy, and as you can see from the code, the Proxy object gets its name from the Proxy’s newProxyInstance method and this newProxyInstance method is interesting, it takes three parameters, the first is the class loader, the second is the interface of the Proxy class, The third is an enhanced class that implements InvocationHandler

Public class TestCase {public static void main(String[] args) {system.out.println (" court "); public static void main(String[] args) {system.out.println (" court "); / / proxy class class files into the local disk, use a decompiler to view the generated code System. SetProperty (DebuggingClassWriter DEBUG_LOCATION_PROPERTY, "D:\wanglihong_gdk"); // Get the enhanced class InvocationHandler lawerHandler = new LawerInvocationHandler<SeeChildSuit>(new Wanglihong()); // Pass in the proxy class loader, proxy class interface, and enhancement class, Get the Proxy class SeeChildSuit seeChildSuitProxy = (SeeChildSuit) Proxy. NewProxyInstance (SeeChildSuit. Class. GetClassLoader (), new Class<? >[]{SeeChildSuit.class}, lawerHandler); / / using the proxy class implement the target method seeChildSuitProxy. SeeChild (); }}Copy the code

Continuing with the newProxyInstance method, the getProxyClass0 method is a bit of a headache. Isn’t that the way to generate a proxy class

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
                          InvocationHandler h) throws IllegalArgumentException {
  
        Class<?> cl = getProxyClass0(loader, intfs);
       。。。
    }
Copy the code

Following the getProxyClass0 method,

private static Class<? > getProxyClass0(ClassLoader loader, Class<? >... interfaces) { return proxyClassCache.get(loader, interfaces); }Copy the code

Originally the proxy class was placed in a cache

private static final WeakCache<ClassLoader, Class<? >[], Class<? >> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());Copy the code

Get the proxy class from the cache. If not, create the proxy class using apply

public V get(K key, P parameter) { Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); . }Copy the code

GenerateProxyClass = generateProxyClass = generateProxyClass = generateProxyClass = generateProxyClass = generateProxyClass = generateProxyClass

public Class<? > apply(ClassLoader loader, Class<? >[] interfaces) {... byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); }Copy the code

In the generateProxyClass method, we learned that creating a proxy class is the process of generating proxy class bytecode. In contrast to static proxies that generate bytecodes while the program is running, bytecodes are generated while the program is running, a bit like changing the wheels on a running wagon.

public static byte[] generateProxyClass(final String var0, Class<? >[] var1, int var2) { ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2); final byte[] var4 = var3.generateClassFile(); . return var4; }Copy the code

To have nothing to explore the bytecode generation process, because this is not the focus of our research, the source has such problems, and began to track the source code for the sake of a problem at the beginning, chasing the chase is dazzling, continually marvel at the subtlety of the code design, opening the chin repeatedly at the same time, has forgotten why had set off.

So when you look at the source code, you need to always remind yourself, don’t pay attention to the details too early, clarify the context, keep the beginner’s mind. So I write part of the source code analysis will not be large sections of the transcription of source code, leaving only the source code analysis route, there is a road in the heart, afraid of the scenery along the way.

We need to know how the proxy class calls the methods of the proxy class, so we need to know what the proxy class looks like. Now that we have the bytecode of the generated proxy class, maybe the secret lies in the bytecode. Use the decompile tool to decompile the bytecode

Decompile bytecode

public final class $Proxy0 extends Proxy implements SeeChildSuit { private static Method m1; private static Method m3; private static Method m2; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final void seeChild() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m3 = Class.forName("com.handlecode.jdk.SeeChildSuit").getMethod("seeChild"); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); }}}Copy the code

As you can see here, the proxy class implements the same interface as the proxied class, and their common methods are also represented in the proxy class, such as the seeChild method, which calls the Invoke method of the InvocationHandler, This echoes the enhanced class that implements the InvocationHandler interface, which is responsible for the definition of the Invoke method, which will be called in the generated proxy class.

No matter how the invoke method of an enhanced class is defined in relation to the business, it is simply called in a proxy class, which perfectly separates the enhanced method from the proxy, both changing and changing without affecting each other, much better than the static proxy.

Static proxies mix agents with enhancements that are business-specific and highly customized. Such a proxy class cannot be reused on other classes that need proxies. Dynamic proxies separate the proxy class from the enhancement code, which defines a method that the proxy class calls at generation time. So when we use the proxy.

3.1.3 Summary of Operation Procedures

1. Prepare the enhancement class, which implements the InvocationHandler interface, adds the enhancement code to the Invoke method and calls the proxied class’s target method.

The generated proxy class has the same target method signature as the generated proxy class, except that the method body is the invoke method that invokes the enhanced class.

3. Call the target method. Calling the target method of the proxy class actually calls the target method of the proxied class.

3.2 Cglib dynamic proxy

Make the proxied class the parent of the proxy class so that both have the same behavior.

In contrast to JDK dynamic proxies, the cglib dynamic proxy does not implement any interface on the target class. Instead, the target class is the parent class and subclasses are generated by bytecode as the proxy class. Therefore, the target class must be inheritable, and if the target class is declared final, cglib dynamic proxies cannot be used.

Methods in the target class must also be declared as public and Protect. In short, the target class can be inherited and the target method can be overridden. Essentially, this is the same purpose as JDK dynamic proxies: to get a copy of the target class.

3.2.1 case

Proxied object

Public class Wanglihong {public void seeChild() {system.out.println (" want to see the child "); }}Copy the code

Strengthen the class

public class LawerMethodInterceptor implements MethodInterceptor{ @Override public Object intercept(Object sub, {system.out.println (" The lawyer prepares the evidence and states the claim: "); Object object = methodProxy.invokeSuper(sub, objects); System.out.println(" Lawyers argue in court "); return object; }}Copy the code

Generate a proxy class that executes the target method

Public class TestCase {public static void main(String[] args) {system.out.println (" court "); public static void main(String[] args) {system.out.println (" court "); / / proxy class class files into the local disk, use a decompiler to view the generated code System. SetProperty (DebuggingClassWriter DEBUG_LOCATION_PROPERTY, System.getProperty("user.dir")+"/cglib/" ); Enhancer enhancer = new Enhancer(); // Set the parent class of the proxy class, hancer.setsuperclass (wanglihong.class); // Add the enhanced class to the generated proxy class through the callback function, enhancer.setCallback(new LawerMethodInterceptor()); Wanglihong Proxy = (Wanglihong)enhancer.create(); // Call the target method proxy.seechild () from the proxy object; }}Copy the code

3.2.2 CGLIb dynamic proxy principle

Cglib dynamic proxy is the same dynamic proxy generation process that we explored in the JDK dynamic proxy generation process, so let’s explore the specific generation process.

3.2.2.1 enhancement class

MethodInterceptor provides a MethodInterceptor that implements the intercept method. The intercept method provides a MethodInterceptor that implements the intercept method. It is important to note that the Intercept method takes four parameters: the first is the proxy object, the second is the target method, the third is the target method parameter, and the fourth is the proxy method generated by the proxy object.

public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable ;
Copy the code

In addition to enhancing code, the enhanced class also calls the target method through reflection. In the enhanced class, the methods of the parent class are reflected through the proxy method generated by the proxy object. In the Intercept Method, one of the quirks is that the Method parameter has both the target Method and the proxy Method, MethodProxy, and finally the proxy Method is reflected. What happens if the Method Method is reflected?

In fact, the generated proxy class is a subclass of the proxy class, using Method reflection, only the generated proxy class Method, not the Method in the parent class, the purpose of our proxy is to proxy the Method in the parent class, so that the subclass Method through reflection call itself into an infinite loop. Calling invokeSuper with the proxy MethodProxy reflects the methods of the parent class, accomplishing exactly what you want. It is important to note that the invokeSuper method called reflection method is not actually a reflection method. Instead, it directly calls the target method of the propped class, which will be explained in more detail below.

public Object intercept(Object sub, Method method, Object[] objects, MethodProxy throws Throwable {system.out.println (" Counsel prepares evidence and states a claim: "); Object object = methodProxy.invokeSuper(sub, objects); System.out.println(" Lawyers argue in court "); return object; }Copy the code
3.2.2.2 Generating proxy Classes
public static void main(String[] args) { Enhancer enhancer = new Enhancer(); // Set the parent class of the proxy class, hancer.setsuperclass (wanglihong.class); // Add the enhanced class to the generated proxy class through the callback function, enhancer.setCallback(new LawerMethodInterceptor()); Wanglihong Proxy = (Wanglihong)enhancer.create(); // Call the target method proxy.seechild () from the proxy object; }Copy the code

The generation of the proxy class is implemented through the encapsulated ASM framework, tracing the create method through the following call:

net.sf.cglib.proxy.Enhancer#createHelper

net.sf.cglib.core.AbstractClassGenerator#create

net.sf.cglib.core.AbstractClassGenerator#get

net.sf.cglib.core.AbstractClassGenerator#generate

net.sf.cglib.core.DefaultGeneratorStrategy#generate

net.sf.cglib.transform.ClassReaderGenerator#generateClass

org.objectweb.asm.ClassReader#accept

By decompiling the bytecode, we can see that the generated proxy class inherits the parent HelloService and overrides the parent sayHello method. In this override method, we can see that the Intercept method in the enhanced class that implements the MethodInterceptor interface is called

public class HelloService$$EnhancerByCGLIB$$e099f798 extends HelloService implements Factory { private static final MethodProxy CGLIB$sayHello$0$Proxy = null; CGLIB$sayHello$0$Proxy = MethodProxy.create(cls3, cls, "()V", "sayHello", "CGLIB$sayHello$0"); public final void sayHello() { MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0; if (methodInterceptor == null) { CGLIB$BIND_CALLBACKS(this); methodInterceptor = this.CGLIB$CALLBACK_0; } if (methodInterceptor ! = null) { methodInterceptor.intercept(this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy); } else { HelloService$$EnhancerByCGLIB$$e099f798.super.sayHello(); }}}Copy the code

It’s worth noting that the MethodInterceptor class is introduced through the setCallback method, whereas the JDK dynamic proxy class is introduced through the newProxyInstance method’s argument. Either way, the generated proxy class must have an enhanced class in order to call the methods in the enhanced class. This is the key to dynamic proxy separation of proxy classes and enhanced code.

3.2.2.3 fastclass mechanism

In the generated proxy class, there is a line of code that takes the first parameter to the propped object, the second parameter to the proxy object, the third parameter to the input type, the fourth parameter to the propped method name, and the fifth parameter to the proxy method name

private static final MethodProxy CGLIB$sayHello$0$Proxy = MethodProxy.create(cls3, cls, "()V", "sayHello", "CGLIB$sayHello$0");
Copy the code

Additional sayHellosayHellosayHello0 $Proxy as MethodProxy passed to enhance class intercept method calls by Proxy class before the target method is also discussed, by MethodProxy can get to the execution of the parent class method, So how do you get a superclass method in MethodProxy? MethodProxy is obviously created here, and the intercept method of the enhanced class uses MethodProxy’s invokeSuper method to get the method of the parent class. Take two steps:

1. Create MethodProxy

net.sf.cglib.proxy.MethodProxy#create

public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
    MethodProxy proxy = new MethodProxy();
    proxy.sig1 = new Signature(name1, desc);
    proxy.sig2 = new Signature(name2, desc);
    proxy.createInfo = new CreateInfo(c1, c2);
    return proxy;
}
Copy the code

The create method is primarily used to instantiate MethodProxy, the Signature entity records the proxy and promentee classes and their corresponding method inputs, and the CreateInfo entity records the proxy and promentee classes.

2. Use MethodProxy to get propped class methods

In the intercept method in enhancing MethodProxy call invokeSuper method net. Sf. Additional. Proxy. MethodProxy# invokeSuper

public Object invokeSuper(Object obj, Object[] args) throws Throwable { try { init(); FastClassInfo fci = fastClassInfo; return fci.f2.invoke(fci.i2, obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); }}Copy the code

2.1 the init method

The init method is used to assign a value to the FastClassInfo entity. FastClassInfo encapsulates two FastClass entities, one for the proxy class and the other for the propped class. Index the two FastClass entities.

It is important to note that the helper method encapsulates the proxy class and the method encapsulated by the proxy class. Before encapsulating the proxy class, you need to retrieve the two classes from the cache. If they are not in the cache, you need to generate new FastClass bytecode with ASM. As a result, cglib dynamic proxies are slower than JDK dynamic proxies at startup, generating not only the proxy classes but also the corresponding FastClasses, just because of the preparation, at code execution time is faster than JDK.

private void init()
{
    if (fastClassInfo == null)
    {
        synchronized (initLock)
        {
            if (fastClassInfo == null)
            {
                CreateInfo ci = createInfo;
​
                FastClassInfo fci = new FastClassInfo();
                fci.f1 = helper(ci, ci.c1);
                fci.f2 = helper(ci, ci.c2);
                fci.i1 = fci.f1.getIndex(sig1);
                fci.i2 = fci.f2.getIndex(sig2);
                fastClassInfo = fci;
                createInfo = null;
            }
        }
    }
}
​
private static class FastClassInfo
{
    FastClass f1;
    FastClass f2;
    int i1;
    int i2;
}
Copy the code

2.2 invoke method

After instantiating the FastClassInfo entity in the init method, the invoke method can invoke the method of the proxyed class stored in the FastClassInfo entity using the index set by FastClassInfo, bypassing the need for reflection calls, which is faster than JDK dynamic proxies. Therefore, the execution speed of CGLIb dynamic proxy is relatively fast.

3.2.3 Summary of Operations

1. Create an enhanced class, implement the MethodInterceptor interface, add the enhanced code to the Intercept method and call the target method

2. Generate the proxy class. In the proxy class, the enhancement class is obtained by setting the callback attribute. The target method in the proxy class actually calls the Intercept method of the enhancement class

3. Call the target method. Using fastClass to cache both the proxy class and the proxied, calling the target method actually calls the target method of the proxied class in the cache.

Finally, the source code involved in this article is attached gitee.com/handlecoder… In addition to source code, running Demo generates bytecode files.

The more pain you experience, the more joy you will experience. I’m the handle, and I’ll see you next time!