What is AOP?

AOP (Aspect Orient Programming), commonly referred to as aspect-oriented Programming, is used as a complement to object orientation to address cross-cutting concerns that are distributed across modules in a system, such as transaction management, logging, caching, and so on. The key of AOP implementation lies in the AOP proxy automatically created by AOP framework. AOP proxy is mainly divided into static proxy and dynamic proxy. The static proxy is AspectJ. Dynamic proxies are represented by Spring AOP. This article will analyze and introduce AspectJ and Spring AOP implementations respectively.

How is springaop implemented?

There are two main types of dynamic proxies in Spring AOP, JDK dynamic proxies and CGLIB dynamic proxies. JDK dynamic proxies receive proxied classes through reflection and require that the proxied classes implement an interface. At the heart of JDK dynamic proxies are the InvocationHandler interface and Proxy class.

If the target class does not implement the interface, Spring AOP chooses to use CGLIB to dynamically proxy the target class. CGLIB (Code Generation Library) is a Code Generation Library that can dynamically generate subclasses of a class at runtime. Note that CGLIB is dynamically proxyed by inheritance, so if a class is marked as final, it cannot be dynamically proxyed using CGLIB.

2.1. JDK Dynamic Proxy

Define an interface class

package org.java.base.springaop; Public interface Service {** * add method */ public void add(); /** * update method */ public void update(); }Copy the code

Implement an interface class

package org.java.base.springaop;
public class ServiceImpl implements Service {
 
 public void add() {
 System.out.println("AService add>>>>>>>>>>>>>>>>>>");
 }


 public void update() {
 System.out.println("AService update>>>>>>>>>>>>>>>"); }}Copy the code

The implementation of dynamic proxy class MyInvocationHandler, the implementation of InvocationHandler interface, and the implementation of the interface invoke method. If you look closely at the Invoke method, it is there that aspect logic is added. The target class method is executed by the mehod. Invoke (Target,args) statement.

package org.java.base.springaop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; Constructor * @param target */ MyInvocationHandler(Object target) {super(); this.target = target; } public Object invoke(Object proxy, Method Method, Object[] args) throws Throwable {// Add logic before program execution, MethodBeforeAdviceInterceptor System.out.println("before-----------------------------"); // Invoke Object result = method.invoke(target, args); / / after the program execution to join logic, MethodAfterAdviceInterceptor System. Out.println ("after------------------------------");
 returnresult; }}Copy the code

The test class, NewProxyInstance (aService.getClass().getClassLoader(),aService.getClass().getinterfaces (), handler); To form.

package org.java.base.springaop; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { Service aService = new ServiceImpl(); MyInvocationHandler handler = new MyInvocationHandler(aService); Service aServiceProxy = (Service) proxy.newProxyInstance (aService); // Proxy creates a Proxy instance for the InvocationHandler implementation class .getClass().getClassLoader(), aService.getClass() .getInterfaces(), handler); AServiceProxy complies with the Service interface aserviceproxy.add (); System.out.println(); aServiceProxy.update(); }}Copy the code

As you can see, custom aspect logic has been added before and after the add and Update methods of the target class ServiceImpl, and the AOP interception mechanism is in effect.

2.2. CGLIB dynamic proxy

Target classes. Cglib does not need to define a unified interface for target classes

package org.java.base.springaop; Public class Base {/** * a simulated add method */ public voidadd() {
 System.out.println("add ------------"); }}Copy the code

Implementation of dynamic proxy class CglibProxy, need to implement MethodInterceptor interface, intercept method. In the proxy, custom section logic is added before and after the add method. The target class add method executes the statement as proxy.invokesuper (Object, ARgs).

package org.java.base.springaop; import java.lang.reflect.Method; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { public Object intercept(Object object, Method method, Object [] args, MethodProxy proxy) throws Throwable {/ / add section of logic (advise), this is a before the target class code execution, is the MethodBeforeAdviceInterceptor. System.out.println("before-------------"); // Execute the target class add method proxy.invokesuper (object, args); / / add section of logic (advise), here is the target class code execution, is the MethodAfterAdviceInterceptor. System.out.println("after--------------");
 returnnull; }}Copy the code

Get the Factory of the enhanced target class, where the enhanced method class object is implemented by Enhancer, as shown below:

package org.java.base.springaop; import org.springframework.cglib.proxy.Enhancer; Public class Factory {/** * get the enhanced target class ** @param proxy * @ after adding logic advicereturn*/ public static Base getInstance(CglibProxy proxy) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Base.class); // The intercept method hancer.setCallback(proxy) is used in CglibProxy. Base = (base) enhancer. Create (); base = (base) enhancer.returnbase; }}Copy the code

The test class

package org.java.base.springaop; public class Testcglib { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); // base is the generated enhanced target class base base = factory.getInstance (proxy); // Base is the generated enhanced target class base base = factory.getInstance (proxy); base.add(); }}Copy the code

Since then, cglib dynamic proxy implementation of AOP interception mechanism has been basically implemented, let’s see how the effect of interception, program execution results are as follows:

Before — — –
The add — –
After — — –

As you can see, custom aspect logic has been added before and after the add method of the target class Base, and the AOP interception mechanism is in effect.

Iii. A brief summary of the two methods of dynamic proxy and CGLIB is as follows:

  • JDK Dynamic Proxy
    • Dynamic proxy functionality based on standard JDK
    • Only for business objects that implement the interface
  • CGLIB
    • AOP proxies are implemented by dynamically subclassing target objects,
    • You need to specify the@EnableAspectJAutoProxy(proxyTargetClass = true)To enforce the use of
    • CGLIB is chosen by default when the business object does not implement any interface