Hello, today to share Spring AOP for everyone, quickly take out a small book to write it down!

1. What is AOP

Aspect Oriented Programming provides another way to think about the structure of programs, which makes up for the deficiency of Object Oriented Programming. In addition to classes, AOP provides facets that modularize concerns, such as transaction management that crosscuts multiple types and objects (the terminology for these concerns is often referred to as crosscutting concerns). Spring AOP is an important component of Spring, but Spring IOC doesn’t rely on Spring AOP, which means you can choose whether to use IT or not, and AOP provides a powerful middleware solution that makes Spring IOC complete. We can use AOP to implement log listening, transaction management, permission control and so on.

1.1. AOP terminology

Aspect: Modularity of a concern that may crosscut multiple objects. Transaction management is a good example of crosscutting concerns in a Java application. In Spring AOP, aspects can be implemented using classes (schema based (XML) style) or @Aspect annotations (AspectJ style) in normal classes.

Join point: a specific point in a program’s execution, such as when a method is called or when an exception is handled. In Spring AOP a join point always represents the execution of a method. Personal understanding: The method AOP intercepts is a join point. By declaring an org. Aspectj. Lang. JoinPoint type parameters we can get connection information in the notice (Advice). This will be illustrated later.

Advice: Action performed at a particular Join point on an Aspect. Notification types include “around”, “before”, “after”, and so on. The types of notifications are discussed later. Many AOP frameworks, including Spring, model interceptors as notifications and maintain a chain of interceptors centered around join points. In short, AOP processing of join points is performed through advice. Advice refers to the code to execute when a method is intercepted by AOP.

Pointcut: Assertions that match Join points. Advice is associated with a pointcut expression and runs on any join point that matches the pointcut. How pointcut expressions match join points is at the heart of AOP, and Spring uses AspectJ as the default pointcut syntax. The expression of the pointcut determines which methods are to be intercepted by AOP, which then executes the corresponding Advice code.

Introduction: Declare additional methods or fields. Spring AOP allows you to introduce a new interface (and its implementation class) to any Advice object. Personal understanding: AOP allows you to dynamically implement new interfaces to proxy objects at run time to accomplish some additional functionality without affecting the functionality of existing objects.

Target object: An object that is advised by one or more aspects, also known as a notified object. Since Spring AOP is implemented through a runtime proxy, this object is always the proxied object. All objects in AOP generate a proxy class, and AOP’s entire process deals with proxy classes.

AOP Proxy: An object created by an AOP framework to implement aspect contracts (including functions such as notifying method execution). In Spring, AOP can be either a JDK dynamic proxy or a CGLIB proxy.

Weaving: Connects aspects to other application types or objects and creates a notified object. This can be done at compile time (using the AspectJ compiler, for example), class load time, and run time. Spring, like other pure AOP frameworks, does weaving at run time. The process of associating a facet with an object and creating a proxy object for that object.

1.2. AOP framework

Spring AOP: Implemented using pure Java, Spring AOP does not require a specialized compilation process or classloader, weaving enhanced code into target classes at run time by proxy.

AspectJ: AspectJ is a java-based AOP framework. Beginning with Spring2.0, SpringAOP introduced support for AspectJ, which extends the Java language by providing a specialized editor that provides horizontal code weaving at compile time.

Dynamic proxy

AOP proxies in Spring can be either JDK dynamic proxies or CGLIB proxies.

2.1. JDK Dynamic Proxy

JDK dynamic proxies are implemented through the java.lang.reflect.proxy class, which calls the newProxyInstance() method to create Proxy objects. For classes that use business interfaces, Spring defaults to using JDK dynamic proxies to implement AOP.

Next, a case study demonstrates JDK dynamic proxies in Spring

1. Create a Java project, import the JAR package required by the Spring framework and publish it to the classpath, as shown below:

2. Create interfaces and write add and delete methods

package com.nynu.qdy.jdk;

public interface UserDao {

public void addUser();

public void deleteUser();
Copy the code

}

3. Create an interface implementation class to implement the methods in the interface and output a statement to the methods

package com.nynu.qdy.jdk;

/ / the target class

public class UserDaoImpl implements UserDao {

Public void addUser() {system.out.println (" addUser "); } public void deleteUser() {system.out.println (" deleteUser "); }Copy the code

}

4. Create the aspect class MyAspect and define methods to simulate permission checking and logging in this class. These two methods represent notifications in the slice

package com.nynu.qdy.aspect;

// Section class: There can be multiple Advice(i.e., enhanced methods)

public class MyAspect {

Public void check_Permissions() {system.out.println (" emulation check permissions.....") ); } public void log() {system.out.println ("....") ); }Copy the code

}

5. Create a proxy class that implements the InvocationHandller interface and writes proxy methods. In the Proxy approach, dynamic proxies are implemented through the Proxy class

The jdkProxy class implements the InvocationHandler interface and implements the Invoke method of the interface, which handles all methods called by the dynamic proxy class. In the created Proxy method createProxy(), the newProxyInstance() method of the Proxy class is used to create the Proxy object. The newProxyInstance() method contains three arguments. The first argument is the classloader of the current class, the second argument represents all interfaces implemented by the proxy object, and the third argument, this, represents the proxy class jdkProxy itself. In the invoke() method, the check_Permissions() and log() methods in the aspect class are executed before and after the execution of the target class method.

6. The test class

Create proxy objects and target objects

Get the object enhanced to the target userDao from the proxy object

Finally, the add and remove methods in the object are called

package com.nynu.qdy.jdk;

public class jdkTest {

Public static void main(String[] args) {// create proxy JdkProxy JdkProxy = new JdkProxy(); UserDao = new UserDaoImpl(); // Create the target object UserDao UserDao = new UserDaoImpl(); // Obtain the enhanced target object from the proxy object UserDao userDao1 = (UserDao) jdkProxy.createProxy(UserDao); // Execute the method userdao1.adduser (); userDao1.deleteUser(); }Copy the code

}

Results 7.

Emulation check permission…..

Add user

Simulation logging….

Emulation check permission…..

Delete user

Simulation logging….

As can be seen from the result, the methods of adding and deleting users in the userDao instance have been successfully called, and the function of checking permissions and logging has been added before and after the call. This dynamic proxy that implements the interface is the JDK dynamic proxy in Spring.

2.2. CGLIB dynamic proxy

JDK dynamic proxies are simple to use, but they have a limitation: objects using dynamic proxies must implement one or more interfaces. If you want to proxy classes that are not implemented, you can use the CGLIB proxy.

CGLIB (Code Generation Library) is a high-performance open source Code Generation package. It uses very low-level byte Code technology to generate a subclass of a specified target class and enhance the subclass. The packages required for CGLIB are already integrated into Spring’s core package, so there is no need to import additional JAR packages during development.

The following is a case to demonstrate the implementation process of CGLIB dynamic proxy

1. Create a target class. The target class does not need to implement any interface, just define the required methods

package com.nynu.qdy.cglib;

/ / the target class

public class UserDao {

Public void addUser() {system.out.println (" addUser "); } public void deleteUser() {system.out.println (" deleteUser "); }Copy the code

}

2. Create a proxy class that implements the MethodInterceptor interface and the Intercept () method in the interface

In this proxy method, we first create a dynamic class object Enhancer, which is the core class of CGLIB. Then the setSuperclass() method of the Enhancer class is called to determine the target object; The following example calls the setCalllback() method to add the callback function, where this represents the CglibProxy class itself; Finally, a return statement is used to return the created proxy class object. The Intercept () method is called when the program executes the target method, and the method runtime executes the enhanced method in the aspect class.

3. The test

Create the test class CglibTest, in which the main method first creates the proxy object and the target object, then obtains the enhanced target object from the proxy object, and finally calls the add and remove methods in the object.

package com.nynu.qdy.cglib;

public class CglibTest {

Public static void main(String[] args) {CglibProxy CglibProxy = new CglibProxy(); // create the target object UserDao UserDao = new UserDao(); // Obtain the enhanced object UserDao userDao1 = (UserDao) cglibproxy.createProxy (UserDao); // Execute the method userdao1.adduser (); userDao1.deleteUser(); }Copy the code

}

Results 4.

Emulation check permission…..

Add user

Simulation logging….

Emulation check permission…..

Delete user

Simulation logging….

You can see from the results that the methods in the target class UserDao were successfully called and enhanced. This proxy without implementing an interface is the CGLIB proxy.

3. AOP implementation based on proxy classes

AOP proxies in Spring are implemented using JDK dynamic proxies by default. Using ProxyFactoryBeans is the most basic way to create AN AOP proxy in Spring.

3.1. Spring notification types

Notifications in Spring can be divided into the following five types, based on the join point of the target class method:

Org. Allane. Intercept. Methodinterceptor (surrounding the notification)

Enhancements are implemented before and after the execution of the target method and can be applied to logging, transaction management, and so on.

Org. Springframework. Aop. MethodBeforeAdvice (pre notice)

Enhancements are implemented before the target method is executed and can be applied to functions such as permission management.

Org.spring Framework aop.AfterReturning Advice

Enhancements are implemented after the target method is executed and can be applied to closing streams, uploading files, deleting temporary files, and so on.

Org. Springframework. Aop. ThrowsAdvice (notice)

Enhancements are implemented after a method throws an exception and can be applied to functions such as exception handling and logging.

Org. Springtramework. Aop. IntroductionInterceptor (introducing notification)

Add new methods and properties to the target class that can be used to modify older versions of the program (enhanced classes).

3.2, ProxyFactoryBean

ProxyFactoryBean is the implementation class of the FactoryBean interface. FactoryBean is responsible for instantiating one Bean, while ProxyFactoryBean is responsible for creating proxy instances for other beans. Common configuration properties in the ProxyFactoryBean class are shown in the following edges:

With a primer on the ProxyFactoryBean class, I’ll demonstrate that Spring uses ProxyFactroyBean to create an AOP proxy with a typical wrap notification example

1. Create a Java project, import the JAR package required by the Spring framework and publish it to the classpath, as shown below:

2. Create a facet class that implements the MethodInterceptor interface and implements the invoke() method in the interface to execute the target method

To demonstrate the effect, the methods of checking permissions and logging are executed before and after the target method, which is the enhanced method, namely notification

3. Create a configuration file and specify a proxy object

The target class and aspect are defined through the < bean > element, and the proxy object is defined using the ProxyFactoryBean class. In the defined proxy object, the < property > child specifies the interface that the proxy implements, the target object of the proxy, the notification that needs to be woven into the target class, and the proxy method, respectively.

4. Create a test class

Results of 5.

Mock check permissions…

Add user

Simulating logging…

Mock check permissions…

Delete user

Simulating logging…

4. AspectJ development

AspectJ is an AOP framework based on the Java language that provides powerful AOP capabilities.

AOP can be implemented using AspectJ in the following ways:

Declarative AspectJ based on XML

Annotation-based declarative AspectJ

4.1. Declarative AspectJ based on XML

Xml-based declarative AspectJ refers to defining aspects, pointcuts, and advice through XML files, all of which must be defined in the < AOP :config > element.

  1. The configuration section

In Spring’s configuration file, the configuration aspect uses the < AOP :aspect > element, This element converts a predefined Spring Bean into a facet Bean, so define a normal Spring Bean (as defined in the code above) in the configuration file first. Once defined, the Bean can be referenced through the ref attribute of the < AOP: Aspect > element.

When configuring an < AOP :aspect > element, you typically specify the id and ref attributes, as shown in the following table.

2. Configure the pointcut

In Spring’s configuration file, pointcuts are defined through the < AOP: Pointcut > element. When an < AOP :pointcut > element is defined as a child of an < AOP :config > element, the pointcut is a global pointcut that can be shared by multiple facets; When an < AOP: Pointcut > element is a child of an < AOP: Aspect > element, the pointcut is valid only for the current aspect.

When defining an < AOP :pointcut > element, you typically specify the id and expression attributes, as shown in the following table.

In the above configuration snippet, execution(* com.itheima.jdk.. (…). ) is a defined pointcut expression meant to match the execution of any method of any class in the com.itheima.JDK package. Execution () is the body of the expression. The first ** indicates the return type. Com.itheima. JDK represents the name of the package to be intercepted, and the second represents the name of the class, which represents all classes. The third is the method name, using all methods; Behind the (…). Represents method parameters, where “” represents any parameter. It’s important to note that,There is a space between the first and the package name.

While the pointcut expression defined in the above example is a common configuration in development, the basic format for pointcut expressions in Spring AOP is as follows:

execution (modi fiers-pattern? ret-type-pattern declaring-type-pattern? name -pattern (param-pattern) throws-pattern?)

Each part of the above format is described as follows.

Modifiers – pattern: Access modifiers that represent defined target methods, such as public, private, etc.

Ret-type-pattern: indicates the return type of the defined target method, such as void and String.

Delaring – type – the pattern: define the target method of the class path, such as com. Itheima. JDK. UserDaolmpl.,

Name – -pattern: indicates the target method to be proxied, such as the add() method.

Param-pattern: indicates the parameters that need to be included by the proxied target method. The target method parameters are empty in the examples in this chapter.

Throws -pattern: Indicates the exception type to be thrown by the proxied target method.

There is a question mark (?) , such as mdifers- Patterm, variable Type-Pattern and throws – Pattern indicate configurable items; The other parts are mandatory.

3. Configure notification

In the configuration code, the five common notifications are configured using the child elements of < AOP: ASPEq > respectively. These five child elements do not support the use of child elements, but some attributes can be specified when used, as shown in the following table.

Now that you know how to configure aspects, pointcuts, and advice in XML files, let’s use a case study to demonstrate how to use the XML-based declarative Aspect J in Spring

1. Create aspect classes and define different types of notifications in each class

In the section class, five different types of notification are defined respectively. In the notification, JoinPoint interface and its sub-interface ProceedingJoinPoint are used as parameters to obtain the class name, method name and method parameters of the target object.

Note that the surround notification must receive a parameter of type ProceedingJoinPoint, return a value of type Object, and throw an exception. Exception notification can be passed in parameters of type Throwable to output exception information.

2. Create a configuration file and write related configurations

3. Create test classes and enhance methods in the classes

Results 4.

Pre-notification: Simulated execution permission check:

The target class is: com. Nynu. Qdy. JDK. Cf7cf UserDaoImpl @ 184

The enhanced target method is: addUser

Surround start: Simulation opens things up before executing target methods…

Add user

Final notification: Release of resources after the simulation method ends

Wrap end: After executing the target method. Turn off simulated things…

Post notification: Simulate logging:

The target method for the embedded enhancement processing is: addUser

4.2 annotation-based declarative AspectJ

Xml-based declarative ApectJ is much more convenient than an AOP implementation based on proxy classes, but it also has the disadvantage of having to configure a lot of code information in Spring files. To address this issue, the AspectJ framework provides a set of annotations for AOP implementations that replace the bloated code configured in Spring configuration files to implement AOP functionality.

For an introduction to AspectJ annotations, see the following table:

To help readers quickly grasp these annotations, re-implement the example in the previous section using annotations as follows

1. Copy the section class from the previous section and modify it accordingly

In the Aspect class, you first define the Aspect class using the @Aspect annotation. Since this class is used as a Component in Spring, you need to add the @Component annotation to take effect. The @poincut annotation is then used to configure pointcut expressions and define methods to represent pointcut names. The corresponding annotations are then added to each notification corresponding method and the pointcut name “myPointCut” is passed as a parameter to the notification method that needs to perform the enhancement. If additional parameters are required, such as exception parameters for exception notification, you can pass the corresponding property values as prompted by the code.

2. The target class com. Itheima. JDK. UserDaolmpl, add annotations @ Repository (” userDao)”

package com.nynu.qdy.jdk;

import org.springframework.stereotype.Repository;

@Repository(“userDao”)

public class UserDaoImpl implements UserDao {

Public void addUser() {system.out.println (" addUser "); } public void deleteUser() {system.out.println (" deleteUser "); }Copy the code

}

3. Create the configuration file applicationContext.xml

The < beans XMLNS: xsi = “www.w3.org/2001/XMLSch…”

xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd "> <! <context:component-scan base-package="com.nynu.qdy" /> <! Aop: Aspectj-autoproxy />Copy the code

4. Create a test class

package com.nynu.qdy.aspectj.annotation;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.nynu.qdy.jdk.UserDao;

public class TestAnnotation {

@SuppressWarnings("resource") public static void main(String[] args) { String xmlPath = "com/nynu/qdy/aspectj/annotation/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); / / 1 content from container UserDao UserDao = (UserDao) applicationContext. GetBean (" UserDao "); // 2 Execute method userdao.adduser (); userDao.deleteUser(); }Copy the code

}

Results of 5.

Surround start: Simulation opens things up before executing target methods…

Pre-notification: Simulated execution permission check:

The target class is: com. Nynu. Qdy. JDK. UserDaoImpl @ 71809907

The enhanced target method is: addUser

Add user

Wrap end: After executing the target method. Turn off simulated things…

Final notification: Release of resources after the simulation method ends

Post notification: Simulate logging:

The target method for the embedded enhancement processing is: addUser

Surround start: Simulation opens things up before executing target methods…

Pre-notification: Simulated execution permission check:

The target class is: com. Nynu. Qdy. JDK. UserDaoImpl @ 71809907

The target method that is embedded with the enhancement is deleteUser

Delete user

Wrap end: After executing the target method. Turn off simulated things…

Final notification: Release of resources after the simulation method ends

Post notification: Simulate logging:

The target method for the embedded enhancement is deleteUser

If multiple notifications need to be executed at the same join point, the order in which the pre-notifications and the surround notifications are executed before the target method is unknown, and the order in which the post-notifications and the surround notifications are executed after the target method is also positional in the same slice.

Well, that’s all for today’s article, hoping to help those of you who are confused in front of the screen