This article is shared from the Huawei Cloud Community " Spring Master's Road 18 - Understanding Spring AOP from the perspective of XML configuration ", author: Zhuan Yeyang__.
1. Spring AOP and dynamic proxy
1.1 The relationship between Spring AOP and dynamic proxy
Spring AOP
Implement aspect-oriented programming using dynamic proxies as its primary mechanism. This mechanism allows Spring
the dynamic creation of proxy objects at runtime. These proxy objects wrap the target object (i.e. business component) to insert additional behaviors (such as security checks, transaction management, logging, etc.) before and after calling the target object's methods. .
-
JDK dynamic proxy
Spring AOP
: The dynamic proxy used by default when the target object implements one or more interfacesJDK
.JDK
Dynamic proxy uses the reflection mechanism to create a proxy object for the interface. This proxy object will intercept all calls to the target interface method. -
CGLIB proxy : If the target object does not implement any interface,
Spring AOP
it will fall back to usingCGLIB
the library to generate a subclass of the target class.CGLIB
(Code Generation Library
) is a powerful high-performance code generation library that extendsJava
classes at runtime and overrides methods in subclasses to implement method interception.
No matter which proxy method is used, the purpose is to insert additional behaviors at different stages of method execution through notifications defined by aspects without changing the original business logic code.
1.2 AOP basic terminology
Aspect : Aspect is the core of aspect-oriented programming. It is a construct that modularizes concerns across multiple classes (such as logging, transaction management, etc.). An aspect can contain multiple types of advice ( Advice
) and one or more pointcuts ( Pointcut
) that define where and when those advices are executed.
Join Point : A join point represents a specific location during program execution, Spring AOP
limiting these locations to method calls. Simply put, a join point is a point where aspect advice can be inserted.
Advice : Advice defines the action to be performed by the aspect at the connection point. Depending on the notification type, these actions can be performed before, after the method is called, after a result is returned, or when an exception is thrown. Notification types include:
- Pre-notification (
Before advice
): executed before the method is executed. - Post-notification (
After advice
): Executed after the method is executed, regardless of its results. - Post-return notification (
After-returning advice
): Executed after the method is successfully executed. - Post-exception notification (
After-throwing advice
): Executed after the method throws an exception. - Surround advice (
Around advice
): Executed before and after method execution, providing full control over method calls.
Pointcut (Pointcut) : Pointcut is an expression. Pointcut expressions allow matching connection points through method names, access modifiers and other conditions, which determines which methods should be triggered when notifications are executed.
Target Object : An object that is notified by one or more aspects. Also called a proxied object.
AOP Proxy : AOP
An object created by the framework to implement aspect contracts (defined by advice and pointcuts). In Spring AOP
, AOP
a proxy can be JDK
a dynamic proxy or CGLIB
a proxy.
Introduction : Introduction allows adding new methods or properties to an existing class. This is Introduction interfaces
achieved by defining one or more additional interfaces ( ), and AOP
the framework creates a proxy for the target object that implements these interfaces.
If it still feels abstract, let’s give another example of film production as an analogy.
Aspect
Imagine someone is filming a movie, and the special effects in the movie (such as explosions and special lighting effects) are like cross-cutting concerns that need to be handled in the application (such as logging or transaction management). These special effects appear in many different scenes of the movie, not just in one specific scene. In AOP
Python, these "effects" are aspects, and they can be applied to multiple parts of the program without changing the actual scene (or code).
Join Point
Continuing with the movie metaphor, a specific moment in each scene, such as the moment an explosion occurs, can be seen as a connecting point. In programming, this usually corresponds to a method call.
Advice
Notifications are like specific instructions from the director to the special effects team, such as "Add an explosion effect before this scene starts" or "Show the smoke dissipating effect after the scene ends." These instructions tell the special effects team at which specific effects should be added at specific moments in the film. In AOP
, these "instructions" are notifications, specifying that aspects (special effects) should be executed before, after, or around join points (specific code execution moments).
Pointcut
If the notice is the director's instruction to the special effects team, then the cutting point is the specific conditions contained in the instruction, such as "all night location scenes." Pointcuts define which connection points (such as which specific method calls) should receive notifications (effect instructions).
Target Object
The target objects are those scenes where special effects need to be added. In our programming metaphor, they are those objects that are affected by aspect logic (such as classes that require logging).
AOP Proxy
AOP
A proxy is like a virtual, controllable copy of a scene provided by the special effects team. This copy appears to the audience to be the same as the original scene, but in fact it automatically adds special effects when the director needs them. In programming, a proxy is an AOP
object automatically created by the framework. It wraps the target object and ensures that notifications (special effect instructions) are executed at the correct time.
Introduction
Introduction is like adding a brand new character or scene to a movie that does not exist in the original script. In AOP
, introduction allows us to add new methods or properties to an existing class, which is like extending the content of a movie without changing the original script.
2. Implement Spring AOP through XML configuration
Spring
Provides rich AOP
support, and can XML
define aspects, notifications ( advice
) and pointcuts ( pointcuts
) through configuration. This allows you to add additional behaviors (such as logging, transaction management, etc.) without modifying the source code.
Implementation steps:
-
Add Spring dependencies
pom.xml
: AddSpring
framework andAOP
related dependencies to the project . -
Define business interfaces and implementation classes : Create business logic interfaces and their implementations, such as a simple service class.
-
Define aspect classes : Create an aspect class to define pre-, post-, and wrap-around notifications.
-
Configuration XML :
applicationContext.xml
Configure aspects, businessbean
, andAOP
related tags in XML.
2.1 Add Spring dependency
In pom.xml
the file, add the following dependencies
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.10</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.10</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency> </dependencies>
2.2 Define business interfaces and implementation classes
First, we define a business logic interface MyService
and its implementation MyServiceImpl
.
MyService.java:
package com.example.demo.aop; public interface MyService { String performAction(String input) throws Exception; }
MyServiceImpl.java:
package com.example.demo.aop; public class MyServiceImpl implements MyService { @Override public String performAction(String action) throws Exception { System.out.println("Performing action in MyService: " + action); if ("throw".equals(action)) { throw new Exception("Exception from MyService"); } return "Action performed: " + action; } }
2.3 Define aspect classes
Next, we define an aspect class MyAspect
that will contain a pre-advice ( advice
) that is executed before MyService
the performAction
method is executed.
MyAspect.java:
package com.example.demo.aop; import org.aspectj.lang.ProceedingJoinPoint; public class MyAspect { // pre-notification public void beforeAdvice() { System.out.println("Before advice is running!"); } // post notification public void afterAdvice() { System.out.println("After advice is running!"); } // Notify after return public void afterReturningAdvice(Object retVal) { System.out.println("After returning advice is running! Return value: " + retVal); } // Notification after exception public void afterThrowingAdvice(Throwable ex) { System.out.println("After throwing advice is running! Exception: " + ex.getMessage()); } //surround notification public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("Around advice: Before method execution"); Object result = null; try { result = joinPoint.proceed(); } finally { System.out.println("Around advice: After method execution"); } return result; } }
2.4 Configuration XML
Finally, we need to configure the above and related content in Spring
the configuration file .applicationContext.xml
bean
AOP
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- The above is the header declaration of the XML file, which defines the version and encoding type of the file, and introduces the namespace of Spring beans and AOP. Through these namespaces, we can use <bean> and <aop:*> tags in XML. --> <!-- Bean definitions --> <bean id="myService" class="com.example.demo.aop.MyServiceImpl"/> <bean id="myAspect" class="com.example.demo.aop.MyAspect"/> <!-- AOP configuration--> <aop:config> <!-- Define aspects and their notifications --> <aop:aspect id="myAspectRef" ref="myAspect"> <!-- Define pointcuts and specify notifications that should be triggered when methods are executed --> <aop:pointcut id="serviceOperation" expression="execution(* com.example.demo.aop.MyService.performAction(..))"/> <!-- Apply pre-notification, specify operations before method execution --> <aop:before method="beforeAdvice" pointcut-ref="serviceOperation"/> <!-- Apply post-notification, specify the operation after the method is executed, whether the method is executed successfully or an exception is thrown --> <aop:after method="afterAdvice" pointcut-ref="serviceOperation"/> <!-- Notification after the application returns, operations after the specified method is successfully executed and returned --> <aop:after-returning method="afterReturningAdvice" pointcut-ref="serviceOperation" returning="retVal"/> <!-- Notification after application exception, action after specified method throws exception --> <aop:after-throwing method="afterThrowingAdvice" pointcut-ref="serviceOperation" throwing="ex"/> <!-- Apply surrounding notifications to provide complete control before and after method execution --> <aop:around method="aroundAdvice" pointcut-ref="serviceOperation"/> </aop:aspect> </aop:config> </beans>
myService : This is business logic bean
and points to MyServiceImpl
an instance of the class.
myAspect : This is aspect bean
, pointing to MyAspect
an instance of the class.
<aop:config>
: This is AOP
the root element of the configuration. All AOP
configurations, including aspect definitions, pointcuts and notification methods, need to be defined inside this element.
Aspect : Defined through <aop:aspect>
elements, it contains a series of advices ( advice
) and one or more pointcuts ( pointcut
). This element associates aspect classes (classes that contain notification logic) with specific operations (how and when to enhance the target object).
Pointcut : Through <aop:pointcut>
element definition, pointcut is specified by expression. When you need to precisely control which methods will trigger notifications when executed, you need to define pointcut. Pointcut expressions can specify methods very precisely, for example by method name, parameter types, annotations, etc. expression
It defines the expression of the pointcut and specifies the matching rules of the pointcut. The expression here execution(* com.example.demo.aop.MyService.performAction(..))
means that the pointcut matches the execution of the method MyService
in the interface performAction
, and the pointcut is used to specify at which connection points ( Join Point
such as method calls) the notification is applied.
About parsing expressionsexecution(* com.example.demo.aop.MyService.performAction(..))
execution : is the most commonly used pointcut function, used to match the connection points of method execution.
*: Indicates that the return type of the method is arbitrary.
com.example.demo.aop.MyService.performAction : Specifies the full path of the interface name and method name.
(…) : Indicates that the method parameters are arbitrary and will match regardless of how many parameters the method has.
-
Join Point : A join point refers to a certain point during program execution, such as a method call. Join points are identified and matched by pointcut ( ) expressions, which define a pointcut that specifies an explicit set of join points—that is, all invocations of methods of the interface . In this example, the interface method calls are potential connection points. Each time a method is called, a join point is reached . This connection point is where the application is notified of its timing.
Pointcut
execution(* com.example.demo.aop.MyService.performAction(..))
MyService
performAction
MyService
performAction
performAction
-
Advice : This is an
AOP
action that enhances the execution of a method by performing actions at specific times.method
The attribute specifies the method name of the aspect that should be executed when the pointcut matches,pointcut-ref
referencing the pointcut defined above. For example, here is the method that is called beforebeforeAdvice
the target method is executed.performAction
This means that wheneverMyService.performAction(..)
a method is called,beforeAdvice
the method will be executed first.
To sum up in one sentence: Spring AOP
By defining rules (cut points) in aspects to specify when (connection points) and how (notifications) to enhance specific methods, the modularization of the code and separation of concerns are achieved without modifying the original business logic.
In this way, Spring AOP
you can define custom logic to be inserted before, after, or around execution of a specific method without modifying the original business logic code. This is a powerful mechanism for achieving separation of concerns, especially for cross-cutting concerns that span multiple parts of the application (such as logging, transaction management, etc.).
Note that if <aop:config>
set to
<aop:config proxy-target-class="true"> <!--Other configuration remains unchanged--> </aop:config>
Setting this proxy-target-class="true"
will cause the proxy Spring AOP
to be used in preference CGLIB
even if the target object implements the interface. By default, proxy-target-class
the property does not need to be set, or if it is set false
, a dynamic proxy is used JDK
.
Main program:
DemoApplication.java:
package com.example.demo; import com.example.demo.aop.MyService; import org.springframework.context.support.ClassPathXmlApplicationContext; public class DemoApplication { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyService myService = (MyService) context.getBean("myService"); try { System.out.println(myService.performAction("normal")); } catch (Exception e) { e.printStackTrace(); } System.out.println("======================="); try { System.out.println(myService.performAction("throw")); } catch (Exception e) { System.out.println("Exception caught in main: " + e.getMessage()); } context.close(); } }
operation result:
By combining dynamic proxy technology with these AOP
concepts, Spring AOP
applications can be provided with support for cross-cutting concerns in a non-intrusive way, allowing developers to modularize these concerns and keep business logic components focused and simple.
If you are interested in the dynamic proxy, you can debug it again. JDK
The dynamic proxy here is because public class MyServiceImpl implements MyService
the interface is implemented. The debugging is as follows:
Let’s briefly talk about the key classes and interfaces that can be seen here.
ProxyFactory : This is Spring AOP
a factory class used to create proxy objects. It can decide to use JDK
dynamic proxy or proxy based on whether the target object implements the interface CGLIB
.
AopProxy : This interface defines methods for obtaining proxy objects. It has two main implementations: JdkDynamicAopProxy
(for JDK
dynamic proxies) and CglibAopProxy
(for CGLIB
proxies).
JdkDynamicAopProxy : Implements AopProxy
the interface and uses JDK
dynamic proxy technology to create a proxy. It implements InvocationHandler
the interface and intercepts all method calls to the proxy object.
CglibAopProxy : Also implements AopProxy
the interface, but uses CGLIB
a library to create proxy objects. For classes that do not implement the interface, Spring
this method will be chosen to create the proxy.
If you want to understand Spring AOP
the source code in depth, you can directly view JdkDynamicAopProxy
the CglibAopProxy
implementation of these two classes. This is not the focus of this article, just briefly mention:
For example, JdkDynamicAopProxy
see the implementation of dynamic proxy in:
-
JdkDynamicAopProxy
Classes implementInvocationHandler
interfaces, which areJDK
the core of dynamic proxying. In itsinvoke
method, there will be logic to determine whether the call needs to be intercepted, and corresponding notifications will be applied before and after the call. -
The process of creating a proxy is mainly done
ProxyFactory
by callingcreateAopProxy()
a method, which returns an instance ofJdkDynamicAopProxy
or according to the configurationCglibAopProxy
. -
Use of proxy: The client code
ProxyFactory
obtains the proxy object and calls the target method through this proxy object. The proxy object usesJdkDynamicAopProxy
or internallyCglibAopProxy
to intercept these calls andAOP
perform notifications based on configuration. The process of obtainingProxyFactory
a proxy objectSpring
is usually done implicitly in the configuration and usage, especially when usingSpring
container managementAOP
. This process does not require the developer to callProxyFactory
the class directly. WhenSpring
one is defined in the configurationbean
and an aspect is applied to it,Spring
the container automatically handles the process of creating the agent and applying notifications. This is achieved throughSpring
post-processor andAOP
namespace support, and developers usually only need to configure aspects and advice declaratively.
If you want to see CGLIB
the agent, here 2
is a way
The third 1
method is to remove the MyServiceImpl
implemented interface, and then change the corresponding place between MyService
the main program and the expression . The third way is to explicitly set the label's properties in the configuration file to achieve this. as follows:expression
MyServiceImpl
2
Spring
<aop:config>
proxy-target-class="true"
<aop:config proxy-target-class="true"> <!--Other configuration remains unchanged--> </aop:config>
Debugging is as follows:
Welcome to one-click triple connection~
If you have any questions, please leave a message and let’s discuss and learn together.
Click to follow and learn about Huawei Cloud’s new technologies as soon as possible~
RustDesk suspended domestic service Taobao (taobao.com) due to rampant fraud, restarted web version optimization work, Apple released M4 chip, high school students created their own open source programming language as a coming-of-age ceremony - Netizens commented: Relying on the defense, Yunfeng resigned from Alibaba, and plans to produce in the future Visual Studio Code 1.89, the destination for independent game programmers on the Windows platform, is officially announced by Huawei. Yu Chengdong’s job adjustment was nailed to the “FFmpeg Pillar of Shame” 15 years ago, but today he has to thank us - Tencent QQ Video avenges its previous shame? The open source mirror station of Huazhong University of Science and Technology is officially open to external network access