1. Meet AOP
1.1 What is AOP
AOP is the abbreviation of Aspect Oriented Programming, which means Aspect Oriented Programming
AOP is a continuation of OOP (object-oriented programming), is a hot topic in software development, capacity is also a very important part in the Spring framework, each part of the business logic to make use of AOP can be isolated, so as to make the business logic between the parts of the coupling is reduced, improve the reusability of the program, at the same time improve the efficiency of development.
benefits
- Enhancements to methods without modifying the source code while the program is running
- Be logical and develop your core business without focusing on code that enhances it
- Reduce repeated code, improve development efficiency, facilitate later maintenance
1.2 AOP low-level implementation
The underlying layer of AOP is implemented through the dynamic proxy technology provided by Spring. During the runtime, Spring dynamically generates proxy objects through dynamic proxy technology. During the execution of proxy object methods, enhancements are carried out to invoke the methods of target objects, thus completing the enhancement of functionality.
1.3 AOP related terminology
- Target: The agent’s Target object (AccountServiceImpl)
- Proxy: When a class is woven into AOP for enhancement, a result Proxy class is produced
- Joinpoint: A Joinpoint is a point that can be intercepted. In Spring, these points refer to methods, because Spring only supports join points of method types
- Pointcut (point) : point refers to the we want to intercept the definition of what Joinpoint (AccountServiceImpl. Transfer ())
- Advice: Advice is what you need to do after intercepting Joinpoint: pre-notification, post-notification, exception notification, final notification, surround notification
(MyAdvice)
- Aspect: Is a combination of a pointcut and an introduction
- Weaving: The process of applying enhancements to target objects to create new proxy objects. Spring uses dynamic proxy Weaving.
1.4 AOP development clarity
1.4.1 Development Stage (what we did)
- Writing core business code pointcuts (target methods for target classes)
- Extract common code and make it a notification (enhancement method) notification
- In the configuration file, you declare the relationship between pointcuts and advice, known as facets
1.4.2 Runtime (Completed by the Spring Framework)
The Spring framework monitors the execution of pointcut methods. Once the pointcut method is monitored to run, the proxy mechanism is used to dynamically create the proxy object of the target object and weave the corresponding function of the notification into the corresponding position of the proxy object according to the notification category to complete the code logic operation.
1.4.3 Low-level proxy implementation
In Spring, the framework decides which dynamic proxy approach to adopt based on whether the target class implements the interface.
- When beans implement interfaces, the JDK proxy mode is used
- < AOP: AspectJAutoProxy proxyt-target-class= “true” /> < AOP: AspectJAutoProxy proxyt-target = “true” />
2. AOP development based on XML
2.1 Project Construction
2.1.1 pom. XML
<dependencies> <! Import the spring context coordinates, Spring Framework </groupId> <artifactId> Spring-context </artifactId> The < version > 5.1.5. RELEASE < / version > < / dependency > <! <dependency> <groupId>org.aspectj</groupId> <artifactId> Aspectjweaver </artifactId> The < version > 1.8.13 < / version > < / dependency > <! <dependency> <groupId>org.springframework</groupId> <artifactId> Spring-test </artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId> The < version > 4.12 < / version > < / dependency > < / dependencies >Copy the code
2.1.2 Service Interfaces
public interface AccountService {
public void transfer();
}
Copy the code
2.1.3 Service Implementation
@Service public class AccountServiceImpl implements AccountService { @Override public void transfer() { System.out.println(" Transfer service executed... ") ); }}Copy the code
2.1.4 notification class
@component public class MyAdvice {public void before(){system.out.println ("... ); }}Copy the code
2.1.5 applicationContext. XML
<? The 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:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <! <context:component-scan base-package="com.lagou"/> <aop:config> <! <aop: Aspect ref="myAdvice"> <! When transferring the target class is configured, < AOP :before method="before" pointcut="execution "(public void com.lagou.service.impl.AccountServiceImpl.transfer())"/> </aop:aspect> </aop:config> </beans>Copy the code
2.1.6 test class
@RunWith(SpringRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class TestAccount { @Autowired private AccountService accountService; @Test public void testTransfer(){ accountService.transfer(); }} ///// pre-notification... Transfer service performed...Copy the code
2.2 XML configuration AOP details
2.2.1 Expression of pointcut
1. Grammar
Execution ([modifier] Return value type package name. Class name. Method name (parameter)Copy the code
- Access modifiers can be omitted
- The return value type, package name, class name, and method name can be replaced with an asterisk (*) to represent any
- A dot between the package name and the class name. Represents the class under the current package. Represents the classes under the current package and its subpackages
- Parameter lists can use two dots.. Represents any number of argument lists of any type
(2) Examples
execution(public void com.lagou.service.impl.AccountServiceImpl.transfer()) execution(void com.lagou.service.impl.AccountServiceImpl.*(..) ) execution(* com.lagou.service.impl.*.*(..) ) execution(* com.lagou.service.. *. * (..) )Copy the code
(3) Expression extraction of tangent point
When multiple enhanced pointcut expressions are the same, the pointcut expression can be extracted. In the enhancement, the pointcut expression can be referenced using the pointcut attribute instead of the pointcut attribute.
<aop:config> <! <aop:pointcut id="myPointCut" expression="execution(public void) com.lagou.service.impl.AccountServiceImpl.transfer())"/> <! <aop: Aspect ref="myAdvice"> <! When transferring the target class is configured, < AOP :before method="before" pointcut ="myPointCut"/> </ AOP :aspect> </aop:config>Copy the code
2.2.2 Notification type
Grammar:
</ AOP: advice type ></ AOP: advice type >Copy the code
The name of the | The label | instructions |
---|---|---|
Pre notice | aop:before | Used to configure pre-notification. Specifies that enhanced methods are executed before pointcut methods |
The rear notice | aop:afterReturning | Used to configure post-notification. Methods that specify enhancements are executed after pointcut methods |
Abnormal notice | aop:afterThrowing | Used to configure exception notification. The specified enhanced method is executed when an exception occurs |
Final notice | aop:after | Used to configure final notification. Executes regardless of whether the pointcut method executes with or without an exception |
Surrounding the notification | aop:around | Used to configure surround notification. Can developers manually control when enhancements are executed |
Note: Generally, surround notifications are used independently
3. AOP development based on XML
3.1 Project Construction
3.1.1 Use annotations to configure weaving relationships in the notification class and upgrade to the aspect class
/** * @author * Created on 2021/06/23 15:03 */ @component @aspect public class MyAdvice {@before ("execution(*) com.lagou.. *. * (..) )") public void before(){system.out.println (" ); }}Copy the code
3.1.2 Enable automatic proxy of AOP
<! < AOP :aspectj-autoproxy />Copy the code
3.2 Annotation configuration OF AOP in detail
3.2.1 Extraction of pointcut expression
/** * @component@aspect public class MyAdvice {@pointcut ("execution(*) com.lagou.. *. * (..) )") public void myPoint() {} @before (" myadvice.mypoint ()") public void Before(){system.out.println (" ); }}Copy the code
3.2.2 Notification type
The name of the | The label | instructions |
---|---|---|
Pre notice | @Before | Used to configure pre-notification. Specifies that enhanced methods are executed before pointcut methods |
The rear notice | @AfterReturning | Used to configure post-notification. Methods that specify enhancements are executed after pointcut methods |
Abnormal notice | @AfterThrowing | Used to configure exception notification. The specified enhanced method is executed when an exception occurs |
Final notice | @After | Used to configure final notification. Executes regardless of whether the pointcut method executes with or without an exception |
Surrounding the notification | @Around | Used to configure surround notification. Can developers manually control when enhancements are executed |
When the four notifications are combined, they are executed in the following order:
@before -> @after -> @afterreturning (if any: @afterthrowing)
3.2.3 Pure Annotation Configuration
(1) Spring configuration class
package com.lagou.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; /** * @author * @date 2021/06/23 20:37 */ @configuration / @componentScan ("com.lagou") // replace <context:component-scan base-package="com.lagou"/> <aop:aspectj-autoproxy /> public class SpringConfig {}Copy the code
(2) Test classes
package com.lagou; import com.lagou.config.SpringConfig; import com.lagou.service.AccountService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; /** * @@runwith (springrunner.class) @contextConfiguration (classes = SpringConfig.class) public class TestAccount { @Autowired private AccountService accountService; @Test public void testTransfer(){ accountService.transfer(); }}Copy the code
4.AOP optimization transfer case
Using the previous transfer case, delete the two agent factory objects directly! Change to spring AOP ideas to implement
4.1 XML configuration implementation
<! --> < AOP :config> <! <aop:pointcut id="myPointcut" expression="execution(* com.lagou.service.. *. * (..) ) "/ > <! < AOP :before method="beginTransaction" pointcut-ref="myPointcut"/> <aop:after-returning method="commit" pointcut-ref="myPointcut"/> <aop:after-throwing method="rollback" pointcut-ref="myPointcut"/> <aop:after method="release" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config>Copy the code
4.2 Annotation configuration implementation
/** * @author * @date 2021/06/23 20:51 */ @component @aspect public class TransactionManager {@autowired ConnectionUtils connectionUtils; @Around("execution(* com.lagou.serivce.. *. * (..) )") public Object around(ProceedingJoinPoint pjp) { Object object = null; Try {/ / open transaction connectionUtils. GetThreadConnection () setAutoCommit (false); // Proceed (); / / to commit the transaction connectionUtils. GetThreadConnection (). The commit (); } catch (Throwable throwable) { throwable.printStackTrace(); . / / rollback transaction try {connectionUtils getThreadConnection (). The rollback (); } catch (SQLException e) { e.printStackTrace(); } } finally { try { connectionUtils.getThreadConnection().setAutoCommit(true); connectionUtils.getThreadConnection().close(); connectionUtils.removeThreadConnection(); } catch (SQLException e) { e.printStackTrace(); } } return object; }}Copy the code