Welcome everyone to pay attention to my public number [old week chat architecture], Java back-end mainstream technology stack principle, source code analysis, architecture and a variety of Internet high concurrency, high performance, high availability of solutions.

What is Spring Aop

Simply put, it is aspect oriented programming. Spring AOP is implemented using dynamic proxies in the JDK for interfaces and CGLIB for classes.

JDK Dynamic proxy

JDK dynamic proxy is the process of dynamically generating proxy class files according to the interface being proxied during the process of program running, and loading and running the process. The purpose of the proxy is to invoke the InvocationHandler’s Invoke method when the target method is invoked, which is actually where Spring AOP plays. This is also a typical proxy pattern. The following simple code illustrates this problem

  • Implement your own InvocationHandler
public class AopProxy implements InvocationHandler {

    private Object realObject;

    public AopProxy(Object realObject) {
        super(a);this.realObject = realObject;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("do something before execute invoke method...");
        Object invokeResult= method.invoke(realObject, args);
        System.out.println("do something after execute invoke method...");
        returninvokeResult; }}Copy the code
  • Define the interface and its implementation class
public interface SubObject {
    public String execute(String... param);
}

public class RealObject implements SubObject {

    @Override
    public String execute(String... param) {
        for (int i = 0; i < param.length; i++) {
            System.out.println(param[i]);
        }
        return "execute method"; }}Copy the code
  • Testing dynamic proxies
public class AppMain {
    public static void main(String[] args) {
        SubObject realObject = new RealObject();
        AopProxy aopProxy = new AopProxy(realObject);
        // Generate a proxy using the JDK proxy
        SubObject subObject = (SubObject) Proxy.newProxyInstance(aopProxy.getClass().getClassLoader(),
                realObject.getClass().getInterfaces(), aopProxy);
        System.out.println(subObject.getClass().getName());
        System.out.println(subObject instanceof Proxy);
        String result =  subObject.execute("Parameter one"."Parameter 2"); System.out.println(result); }}Copy the code
  • The output
com.sun.proxy.$Proxy0 true do something before execute invoke method... Do something after execute invoke method... execute methodCopy the code

Com.sun.proxy.$Proxy0 is a proxy class dynamically generated by the JDK. SubObject instanceof proxy printed as true indicates that the proxy class inherits from the proxy class.

A question arises here: Why do JDK dynamic proxies have to be interface-based?

Here’s why:

  • The generated Proxy class inherits from the Proxy. Because Java is a single inheritance, it can only implement the interface through the interface
  • In terms of the design of the proxy pattern, it makes full use of the polymorphic characteristics of Java and conforms to the specification based on interface coding

Of course, the JDK also states in the proxy generation argument that you need to pass in the corresponding interface

public static Object newProxyInstance(ClassLoader loader, Class
       [] interfaces, InvocationHandler h)
        throws IllegalArgumentException
Copy the code

Additional agent

CGLIB low-level: Uses the bytecode processing framework ASM to convert bytecode and generate new classes. A CGLIB (CODE GENERLIZE LIBRARY) agent is a class implementation agent that generates a subclass of the specified class and overwrites all the methods in it, so the class or method cannot be declared final.

If the target object does not implement an interface, the CGLIB proxy is used by default. If the target object implements the interface, you can force the proxy to be implemented using CGLIB.

Add the CGLIB library and add the <aop:aspectj-autoproxy proxy-target-class="true"/>Copy the code