preface

Because of the holiday reason, there is a period of time did not update to everyone! And we say a thing, the holiday when a fan and I said their own abuse experience, in the holiday before he went to an Internet company interview, the results were directly the other people interview officer Spring AOP three even asked to ask a face meng force! Actually, I think it’s pretty simple, isn’t it?

Before you learn AOP, if you know the proxy pattern, it is very easy to learn. Next, I will introduce AOP to you this important knowledge point!

The proxy pattern

The proxy pattern is a common design pattern in Java development. The design goal is to insert additional functionality between the service class and the client class that is transparent to the caller and acts as a masquerade of control. Examples of renting: tenant, agent, landlord. Corresponding to the proxy mode: customer class, agent class, delegate class (proxy class).

Provide a proxy (proxy class) for an object (delegate class) that controls access to that object. Delegate classes and proxy classes have a common parent class or parent interface. The proxy class preprocesses, filters, and assigns requests to specific objects.

Common agents in life: rental agencies, wedding companies, etc

Two design principles for the proxy pattern:

  1. Proxy classes have similar behavior to delegate classes (common)
  2. Proxy classes enhance the behavior of the delegate class

Common proxy modes:

  1. Static agent
  2. A dynamic proxy

Static agent

An object provides a proxy with a fixed role to control access to the object. Proxy classes and delegate classes have a common parent class or parent interface, so proxy objects can be used wherever delegate objects are used. The proxy class is responsible for pre-processing, filtering, dispatching requests to the delegate class for processing, and subsequent processing after the delegate class executes the request.

The three elements of agency

  • Have common behavior (marriage) – interface

  • Target role (Newcomer) – Actualizing behavior

  • Agent role (wedding company) – Implement behavior enhance target object behavior

Characteristics of static proxies

  1. Fixed target role
  2. Get the target role before the application executes
  3. Proxy objects enhance the behavior of target objects
  4. It is possible to have multiple agents, causing a “quasi-explosion” (disadvantage)

Static proxy implementation

Define the behavior (collectively) define the interface

Public interface Marry {public void toMarry(); }Copy the code

Target object (Implementation behavior)

Public class implements Marry {public void toMarry() {public void toMarry() { System.out.println(" I'm getting married...") ); }}Copy the code

Proxy objects (implement behavior, enhance behavior of target objects)

/** * public class MarryCompanyProxy implements Marry {// Private Marry; // Pass the target object to public MarryCompanyProxy(Marry) {this. Marry = Marry; } public void toMarry() {public void toMarry(); // Execute the method in the target object marry. ToMarry (); // enhance behavior after(); } / private void after() {system.out.println (); ); } private void before() {system.out.println () {system.out.println (); ); }}Copy the code

Implement the function of the target object through the proxy object

// You You = new You(); MarryCompanyProxy = new MarryCompanyProxy(you); MarryCompanyProxy = new MarryCompanyProxy(you); / / by proxy object to invoke methods on the target object marryCompanyProxy. ToMarry ();Copy the code

Static proxy has a fixed role for proxy. For example, there are 20 DAO classes in the DAO layer. If you want to proxy the access rights of methods, you need to create 20 static proxy roles, which causes class explosion and cannot meet the needs of production.

A dynamic proxy

Dynamic proxies are more flexible in creating proxy objects than static proxies. The bytecodes of dynamic proxy classes are generated dynamically by Java reflection while the program is running. It dynamically creates proxy objects for the target object at the runtime of the program through reflection mechanism as needed, without the programmer writing its source code manually. Dynamic proxy not only simplifies the programming work, but also improves the scalability of the software system, because reflection mechanism can generate any type of dynamic proxy class. The behavior of the agent can delegate multiple methods to meet production needs and achieve code generality.

Dynamic proxy can be implemented in two ways:

  1. JDK dynamic proxy
  2. CGLIB dynamic proxy

Dynamic proxy characteristics

  1. The target object is not fixed
  2. The target object is created dynamically while the application is executing
  3. Proxy objects enhance the behavior of target objects

JDK dynamic proxy

Note: The target object of the JDK dynamic proxy must have an interface implementation

newProxyInstance

The Proxy class:

The Proxy class is an action class that implements the Proxy. It can be used to dynamically generate implementation classes for one or more interfaces. This class provides the following actions:

/* Returns an instance method call of a proxy class with the specified interface dispatched to the specified call handler. Loader: A ClassLoader object that defines which ClassLoader objects load interfaces on the generated proxy objects: An array of Interface objects that represents the set of interfaces I am going to provide to the object I want to proide. If I provide an Interface to the object, then the proxy object claims to implement the Interface (polymorphic), so THAT I can call the methods in the Interface: An InvocationHandler interface that represents the interface implemented by the InvocationHandler of the proxy instance. Each proxy instance has an associated invocation handler. When calling a method on a proxy instance, The invoke method (a subclass of the InvocationHandler interface passed in) that encodes the method call and assigns it to its call handler */ public Static Object newProxyInstance(ClassLoader) loader, Class<? >[] interfaces, InvocationHandler h)Copy the code

Getting a proxy object

Public class javkHandler implements InvocationHandler {private Object target; Public JdkHandler(Object target) {this.target = target; * @param proxy the proxy instance that calls the method * @param method the method of the target Object * @param args the method parameter of the target Object * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object [] args) throws Throwable {/ / enhance behavior System. Out. Println (" = = = = = = = = = = = = = = method before execution "); Object result = method.invoke(target,args); / / enhance behavior System. Out. Println (" method executed after = = = = = = = = = = = = = = "); return result; Public static Object newProxyInstance(ClassLoader, * Class<? >[] interfaces, * InvocationHandler h) * loader: interfaces: * * * @return */ Public Object getProxy() {return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterface s(),this); }}Copy the code

Implement the function of the target object through the proxy object

// You You = new You(); JdkHandler = new JdkHandler(you); Marry marry = (Marry) jdkHandler.getProxy(); // Call the target object's method marry. ToMarry () through the proxy object;Copy the code

Q: How is invoke invoked in a Java dynamic proxy class?

A: In the generated dynamic Proxy class Proxy0. Class, the constructor calls the constructor of the parent proxy. class and assigns the value to the member variable invocationHandler. Proxy0. Class, the constructor calls the parent proxy. class constructor and assigns the invocationHandler to the member variable. The static module of proxy0.class creates the proxied class’s method, and the invoke () method of InvocationHandler, a member variable of the parent class, is invoked when the corresponding method is called.

Note: JDK dynamic proxies rely on interface implementation. If some classes do not have an interface implementation, JDK proxies cannot be used.

CGLIB dynamic proxy

The dynamic proxy mechanism of the JDK can only be used to delegate classes that implement the interface, and classes that do not implement the interface cannot use the JDK dynamic proxy mechanism. The principle of cglib is to generate a subclass of the specified target class, and override the method implementation enhancement. Therefore, final modified classes cannot be propped up.

Add the dependent

Introduce cglib dependencies in the POM.xml file

<! -- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> < artifactId > additional < / artifactId > < version > 2.2.2 < / version > < / dependency >Copy the code

Define the class

Implements the MethodInterceptor interface

Public class CglibInterceptor implements MethodInterceptor {private Object target; Public CglibInterceptor(Object target) {this.target = target; Public Object getProxy() {public Object getProxy() {public Object getProxy() { Enhancer = new Enhancer(); // Set the parent class(with the target class as its parent) enhancer.setsuperclass (target.getClass()); // Set the interceptor callback object to its own object, enhancer.setcallback (this); // Generate a proxy class object and return enhancer.create(); } /** * interceptors * 1, method calls to target objects * 2, enhanced behavior * @param object dynamically generated proxy class instance * @param method called by the entity class referenced by the proxy method * @param Objects Parameter value list * @param methodProxy Proxy class that generates a proxy reference to a method * @return * @throws Throwable */ @Override Public Object Intercept (Object object, Method method, Object[] objects, MethodProxy MethodProxy) throws Throwable {// Enhance behavior system.out.println (" execute before ============== method "); // Call a method on the target Object (return Object) Object result = methodProxy.invoke(target,objects); / / enhance behavior System. Out. Println (" method executed after = = = = = = = = = = = = = = "); return result; }}Copy the code

A method is called

// You You = new You(); CglibInterceptor cglibInterceptor = new CglibInterceptor(you); Marry marry = (Marry) cglibInterceptor.getProxy(); marry.toMarry(); User user = new User(); CglibInterceptor cglibInterceptor = new CglibInterceptor(user); User u = (User) cglibInterceptor.getProxy(); u.test();Copy the code

Differences between JDK agents and CGLIB agents

  • JDK dynamic proxy implementation interface, Cglib dynamic proxy inheritance idea
  • JDK dynamic proxies (when the target object has interfaces) perform more efficiently than Ciglib
  • Select the JDK proxy if the target object has an interface implementation, or the Cglib proxy if no interface implementation exists

Spring AOP

Problems caused by log processing

We have a Pay (interface) and then two implementation classes DollarPay and RmbPay need to rewrite the Pay () method. In this case, we need to monitor the performance of the Pay method, add logs and so on. How do we do that?

The easiest way to think about it

Write logging code for each character method, as follows

Disadvantages: too much code duplication, too much coupling added to the logging code (if you need to change the logging code functional requirements, all the methods in the class need to change, a lot of work)

Improve the solution with the decorator pattern/proxy pattern

Decorator pattern: Dynamically add some additional responsibilities to an object.

Proxy mode: Just mentioned. Hence the following structure:

Found after the careful consideration even though no changes to the original internal code, do log processing for each class, and reference to the target class, but if the number of business class to add a lot of, the manual for each business class implements a decorator or create corresponding proxy class, at the same time, the coupling of the code, once the demand change, You can imagine the amount of work.

Is there a better solution to write the code once, reuse the code where you want to add logging, achieve loose coupling, and still function perfectly?

The answer is yes, such a technology exists, and AOP already provides a perfect implementation for it!

What is AOP?

Aspect Oriented Programing, compared with OOP object-oriented programming, Aop is no longer concerned about a class in the program code, some methods, and Aop consideration is more of a face to face cut, that is, between layers of a cut, so it is called the cut. Think of hamburgers (with meat in the middle). So how does AOP intercept the entire aspect? Consider the servlet filter /* configuration you learned earlier, which is actually an AOP implementation.

What can AOP do?

AOP is mainly used in logging, performance statistics, security control, transaction processing and other aspects to achieve the reuse of common functions.

The characteristics of AOP

  1. Reduce the degree of coupling between modules and improve the degree of aggregation of business codes. (High cohesion and low coupling)
  2. Improved code reuse
  3. Improved code reuse
  4. New functionality can be added without affecting existing functionality

The underlying implementation of AOP

Dynamic Proxy (JDK + CGLIB)

Basic concepts of AOP

For every point intercepted, spring refers to every method intercepted, a Spring AOP join point represents the execution of a method.

Pointcut

Spring has a special expression language definition for intercepting join points (matching rule definitions specify which methods to intercept and which methods to process).

Advice (Advice)

Intercept what to do after each join point (each method)

  1. Pre notification (pre enhancement) – Before () notification before method execution
  2. Return notification (Return enhancement) – After the afterReturn method completes the return notification normally
  3. Exception throw notification (Exception throw enhancement) — afetrThrow()
  4. Final notification – after this notification is executed regardless of whether the method has an exception.
  5. Circular advice – around advice that surrounds a join point, such as a method call. This is the most powerful type of notification. Wraparound notification enables custom behavior before and after a method call. It also chooses whether to continue with the join points or simply return their own return values or throw an exception to end execution.

Aspect (Aspect)

A pointcut, in combination with advice, determines the definition of a section. Pointcuts define which methods of which classes to intercept, and advice defines what to do once a method has been intercepted. A section is an abstraction of a crosscutting concern, similar to a class, which is an abstraction of an object’s characteristics.

Target = Target object

The target object to be proxied

Weave (Weave)

The process of applying a facet to a target object and generating a proxy object is called weaving

Introduction

The process of dynamically adding methods or fields to a class at runtime without modifying the original application code is called import

Implementation of Spring AOP

Spring AOP environment setup

Coordinate dependency introduction

<! --Spring AOP--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> The < version > 1.8.9 < / version > < / dependency >Copy the code

Add the configuration of spring.xml

Adding a namespace

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
Copy the code

Annotations to realize

Define the plane

/** * Aspects * Abstraction of pointcuts and advice (similar to classes in object-oriented) * Definition of pointcuts and advice (pointcuts define which methods of which classes to intercept, The notification defines what to do if the method is intercepted.) */ @component // Gives the object to the IOC container to instantiate @aspect // declares the current class to be a facet public class LogCut {/** * pointcut: * matching rules. Specify what methods are blocked and what methods need to be handled * Define pointcuts * @pointcut (" matching rules ") * * Introduction to Aop Pointcut expressions * 1. Execution of any public method: * execution(public *(..)) Execution of any set method * execution(* set*(..)) (* com.xxxx.service.*.*(..)); (* com.xxxx.service. * com.xxxx.service (* com.xxxx.service (* com.xxxx.service)); *. * (..) Private, protected, public (*) */ @pointcut ("execution (* com.xxxx.service.. *. * (..) ** Before(value = "cut()") public void cut(){} public void cut(){} public void Before(); {system.out. println(" pre-notification.....") ); } /** * Return notification and apply the notification to the defined pointcut ** / @afterreturning (value = "cut()") public void afterReturn() { System.out.println(" return notification....." ); } public void After(value = "cut()") public void After() {} public void After() { System.out.println(" final notification....." ); } /** * Declare an exception notification and apply the notification to the defined pointcut */ @afterthrowing (value="cut()",throwing =" e") public void AfterThrow (Exception e) {system.out.println (" Exception notification.....") + "LLDB cause: + LLDB cause ()); } /** * declare the surround advice and apply the advice to the pointcut * define the corresponding processing by the surround advice before and after method execution * the corresponding method needs to be explicitly called otherwise the specified method cannot be accessed (pjp.proceed();) * @param pjp * @return */ @Around(value = "cut()") public Object around(ProceedingJoinPoint pjp) { System.out.println(" pre-notification... ); Object object = null; try { object = pjp.proceed(); System.out.println(pjp.getTarget() + "======" + pjp.getSignature()); // system.out. println(" return notification...") ); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println(" Exception notification...") ); } system.out. println(" Final notification...") ); return object; }}Copy the code

Configuration file (spring.xml)

<! < AOP :aspectj-autoproxy/>Copy the code

XML realize

Define the plane

** * Aspects * Abstraction of pointcuts and advice (similar to classes in object-oriented) * Definition of pointcuts and advice (pointcuts define which methods of which classes to intercept, Public class LogCut02 {public void cut(){} /** * Declare a pre-notification Public void before() {system.out.println (" pre-notification.....") ); } public void afterReturn() {system.out.println (" Return notification.....")} public void afterReturn() {system.out.println (" return notification.....") ); } public void after() {system.out.println (" final notification.....")} public void after() {system.out.println (" final notification.....") ); } public void afterThrow(Exception e) {system.out.println (" Exception notification.....")} public void afterThrow(Exception e) {system.out.println (" Exception notification.....")  + "LLDB cause: + LLDB cause ()); } /** * declare the surround advice and apply the advice to the pointcut * define the corresponding processing by the surround advice before and after method execution * the corresponding method needs to be explicitly called otherwise the specified method cannot be accessed (pjp.proceed();) * @param PJP * @return */ Public Object around(ProceedingJoinPoint PJP) {system.out.println ("... ); Object object = null; try { object = pjp.proceed(); System.out.println(pjp.getTarget() + "======" + pjp.getSignature()); // system.out. println(" return notification...") ); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println(" Exception notification...") ); } system.out. println(" Final notification...") ); return object; }}Copy the code

Configuration file (spring.xml)

<! --> <aop:config> <! <aop:aspect ref="logCut02"> <! < AOP :pointcut id="cut" expression="execution(* com.xxxx.service.. *. * (..) ) "/ > <! Aop :before method="before" pointcut ="cut"/> <aop:before method="before" pointcut ="cut"/> <! Aop :after-return method="afterReturn" pointcut ="cut"/> <aop:after-return method=" pointcut "/> <aop:after-return method=" pointcut" Aop :after-throwing method="afterThrow" throwing="e" pointcut-ref="cut"/> <aop:after-throwing method="afterThrow" throwing="e" pointcut-ref="cut"/> <! Aop :after method="after" pointcut ="cut"/> <aop:after method="after" pointcut ="cut"/> <! < AOP :around method="around" pointcut-ref="cut"/> </ AOP :aspect> </aop:config>Copy the code

Spring AOP summary

The proxy pattern implements three elements

  1. The interface definition
  2. The target object and the proxy object must implement a unified interface
  3. A proxy object holds a reference to a target object, enhancing its behavior

The proxy pattern implements classification and corresponding distinction

  1. Static proxy: Manually create proxy objects for the target object, that is, create proxy objects during program compilation
  2. Dynamic proxy: Dynamically creates the proxy object corresponding to the target object during the program running time.
  3. JDK dynamic proxy: The propped target object must implement some interface or set of implementations to create a proxy object through callbacks.
  4. Cglib dynamic proxy: The proxied target object can be implemented by inheritance without implementing an interface

Dynamic agent compared with static agent, improve the development efficiency, can create mass agents, improve code reuse rate.

Aop understand

  1. Aspect oriented, instead of OOP, focuses on layers or planes in code
  2. Decouple and improve system scalability
  3. Improved code reuse

Aop keywords

  1. Join points: Each method
  2. Pointcut: A collection of matched methods
  3. Aspect: The set of join points and pointcuts determines the aspect, the abstraction of crosscutting concerns
  4. Notifications: Several types of notifications
  5. Target object: the proxied object
  6. Weaving: The process of applying facets to target objects and generating proxy objects at run time
  7. Import: The process of dynamically introducing methods or fields into a program at runtime without modifying the original code

The last

Thank you for reading here, the article has any deficiencies also please correct, think the article is helpful to you remember to give me a thumbs-up!