[Spring] Spring's first understanding of AOP

What is AOP?

AOP is the abbreviation of Aspect Oriented Programming, which means: face-to-face programming. Spring provides rich support for face-to-face programming, which allows cohesive development by separating application business logic and system level services.

Why AOP

Application objects only implement what they should do - complete the business logic - that's all. AOP can be used to isolate all parts of the business logic, which reduces the coupling between the parts of the business logic, improves the reusability of the program, simplifies the code and improves the efficiency of development. If AOP is not used, for example, the following business logic layer code:

package cn.jingpengchong.calculator.service;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService {

	public int div(int a, int b) {
		System.out.println("Journal: The div method begins");
		System.out.println("Journal: The div method args:["+a+","+b+"]");
		return a/b;
	}
}

This example does not use spring's AOP function, so its main method is "return a/b;" however, in order to print the log information, it needs two lines of code, which is very cumbersome. And if you want to extend another multiplication function, you still need to write these two lines of code, which is very tedious. So how to solve such a cumbersome matter? Of course, the AOP function provided by spring is used.

How to use AOP: using annotations

Firstly, add "< AOP: AspectJ AutoProxy / > tag in the xml configuration file, then write the independent module (also known as facet) and pointcut (method in the module) that need to cut into the business process, add" @ Aspect "annotation in front of the class of the independent module and the annotation that can scan it into the IOC container, and add the annotation corresponding to the processing method in front of the pointcut (method)

The comments before the pointcut are as follows:
  • @Before(value = ""): preprocessing, which is used to perform some operations before the execution of the annotation matching method;
  • @After(value = ""): post processing, used to perform some operations after the annotation matching method is executed;
  • @Afterreturning (value =, returning =): return processing, used to perform some operations after the result is returned by the method matching the annotation;
  • @Afterthrowing (value =, throwing =): exception handling, which is used for some operations after the method matching the annotation returns an exception;
  • @Around(value = ""): surround processing, which can be processed in related links by self coding according to requirements.
Note:
  • The value attribute is used to match the method to be processed;
  • The returning property is used to receive the return value;
  • The throwing property is used to receive the exception object;
  • @Difference between After and @ AfterReturning:
    • @The method of After annotation is executed before that of @ AfterReturning annotation;
    • @When an exception is encountered, the method of the After annotation still executes, while the method of the @ AfterReturning annotation does not.
For example, @ Before, @ After, @ AfterReturning and @ Around annotations are used to process each step of the above service layer method execution

1. Delete the code of the service layer method printing log

package cn.jingpengchong.calculator.service;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService {

	public int div(int a, int b) {
		return a/b;
	}
}

2. Add the tag to the spring xml file: Auto proxy

<aop:aspectj-autoproxy/>

3. Create a new independent module "cn.jingpengchong.aspect", where the new file "CalculatorService.java" is as follows:

package cn.jingpengchong.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class CalculatorAspect {

	//Preprocessing
	@Before("execution(public int cn.jingpengchong.calculator.service.CalculatorService.*(..))")
	public void before(JoinPoint jp) {
		Object[] args = jp.getArgs();
		Signature signature = jp.getSignature();
		String name = signature.getName();
		System.out.println("Journal: The " + name + " method begins");
		System.out.println("Journal: The " + name + " method args:[" + args[0] + "," + args[1] + "]");
	}
	
	//Post processing
	@After("execution(public int cn.jingpengchong.calculator.service.CalculatorService.*(..))")
	public void after(JoinPoint jp) {
		Signature signature = jp.getSignature();
		String name = signature.getName();
		System.out.println("Journal: The " + name + " method ends");
	}
	
	//Return processing
	@AfterReturning(value = "execution(public int cn.jingpengchong.calculator.service.CalculatorService.*(..))", returning = "result")
	public void afterReturning(JoinPoint jp, Object result) {
		Signature signature = jp.getSignature();
		String name = signature.getName();
		System.out.println("Journal: The " + name + " method result:" + result);
	}
	
	//exception handling
	@AfterThrowing(value = "execution(public int cn.jingpengchong.calculator.service.CalculatorService.*(..))", throwing = "e")
	public void afterThrowing(JoinPoint jp, Exception e) {
		Signature signature = jp.getSignature();
		String name = signature.getName();
		System.out.println("Journal: The " + name + " method exception:" + e);
	}
}

4. Write test class:

package cn.jingpengchong.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.jingpengchong.calculator.service.ICalculatorService;

public class Test {
	
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
		ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
		System.out.println(calculatorService.div(6, 2));
		applicationContext.close();
	}
}

The operation results are as follows:

Attachment:

1. Each method in the "CalculatorService.java" file above needs to write a long Parameter annotation. We can define a tangent point in this file to extract the parameters of these annotations:

@Pointcut("execution(public int cn.jingpengchong.calculator.service.CalculatorService.*(..))")
public void pointCut() {		
}

In this way, the parameters of the above annotation can be written as "pointCut()", which further simplifies the code.
2. If it is too cumbersome to define four methods in the "CalculatorService.java" file, you can use the "@ Around" annotation to encapsulate the processing in one method:

//Surround processing
@Around("pointCut()")
public Object around(ProceedingJoinPoint pjp) {
	Object result = null;
	Object[] args = pjp.getArgs();
	String name = pjp.getSignature().getName();
	try {
		try {
			//Preprocessing
			System.out.println("The " + name + " method begins");
			System.out.println("The " + name + " method args:[" + args[0] + "," + args[1] + "]");
			result = pjp.proceed();
		}finally {
			//Post processing
			System.out.println("The " + name + " method ends");
		}
		//Return processing
		System.out.println("The " + name + " method result:" + result);
	} catch (Throwable e) {
		//exception handling
		System.out.println("The " + name + " method exception:" + e);
	}
	return result;
}

How to use AOP: using spring's xml configuration file

1. Take the log processing the service layer method as an example:

package cn.jingpengchong.calculator.service;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService {

	public int div(int a, int b) {
		return a/b;
	}
}

2. Create a new independent module "cn.jingpengchong.aspect", in which the new file "LogAspect.java" is as follows:

package cn.jingpengchong.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;

public class LogAspect {

	public void before(JoinPoint jp) {
		Object[] args = jp.getArgs();
		Signature signature = jp.getSignature();
		String name = signature.getName();
		System.out.println("Journal: The " + name + " method begins");
		System.out.println("Journal: The " + name + " method args:[" + args[0] + "," + args[1] + "]");
	}
}

3. Make the following configuration in spring's xml configuration file:

<?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-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<context:component-scan base-package="cn.jingpengchong"></context:component-scan>
 
	<bean id = "logAspect" class = "cn.jingpengchong.aspect.LogAspect"/>
	
	<aop:config>
		<aop:pointcut expression="execution(public int cn.jingpengchong.calculator.service.CalculatorService.*(..))" id="pointCut"/>
		<aop:aspect ref="logAspect">
			<!--Take preprocessing as an example. Other processes are similar-->
			<aop:before method="before" pointcut-ref="pointCut"/>
		</aop:aspect>
	</aop:config>
</beans>

4. Write test class:

package cn.jingpengchong.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.jingpengchong.calculator.service.ICalculatorService;

public class Test {
	
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
		ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
		System.out.println(calculatorService.div(6, 2));
		applicationContext.close();
	}
}

The operation results are as follows:

113 original articles published, 15 praised, 1720 visited
Private letter follow

Tags: calculator Spring xml Java

Posted on Tue, 04 Feb 2020 06:39:33 -0800 by tensionx