Detailed steps of xml-based AOP in Spring

The whole process of Aop is Aspect Oriented Programming, that is, aspect-oriented programming, a technology that achieves the same maintenance of program functions through pre-compilation and runtime dynamic agents. Aop is a continuation of oop, a hot spot in software development, and an important content in the Spring framework. It is a derivative example of functional programming. Aop can be used to divide various parts of business logic, thereby reducing the coupling between various parts of business logic, improving the reusability of programs, and improving development efficiency. Simply put, it is to extract the repetitive code in our program, when it needs to be executed, use the technology of dynamic proxy, and enhance the existing methods on the basis of not modifying the source code, (implemented by means of dynamic proxy)

Related terms

JoinPoint: link points that are intercepted. In spring, these points refer to methods, because spring only supports method types of connection points

Pointcut: The entry point refers to the definition of which JoinPont we want to intercept

Advice: Notification/enhancement is to notify after intercepting Joinpoint

Notification types: pre-notification, post-notification, exception notification, final notification, surround notification

Introduction: Introduction is a special kind of notification. On the premise of not modifying the class code, Introduction can dynamically add some methods or fields to the class during runtime.

Target: target object, the target object of the agent

Weaving refers to the process of applying enhancements to the target object to create new proxy objects. Spring uses dynamic proxy weaving, while AspectJ uses compile-time weaving and class-loading weaving.

Proxy: proxy, after a class is woven and enhanced by Aop, a result proxy class is generated

Aspect: Aspect is a combination of entry point and notification (introduction)

In spring, the framework will decide which dynamic proxy method to use based on whether the target class implements the interface.

AOP steps based on XMl

1. Create a Maven project to introduce spring coordinates

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.mingqi</groupId>
 <artifactId>SpringIOC</artifactId>
 <packaging>pom</packaging>
 <version>1.0-SNAPSHOT</version>
 <dependencies>
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.0.2.RELEASE</version>
 </dependency>
 <dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.7</version>
 </dependency>
 <dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
 </dependency>
 </dependencies>
</project>

2. Create a business layer interface

package com.mingqi.services;
public interface IAccountService {
    
    
 /**
 * 模拟登陆账户
 */
 void saveAccount();

 /**
 * 模拟更新账户
 * @param id
 */
 void updateAccount(int id);

 /**
 * 模拟删除账户
 * @return
 */
 int deleteAccount();

}

3. Create a business layer implementation class

package com.mingqi.services.impl;
import com.mingqi.services.IAccountService;
public class AccountServicesImpl implements IAccountService {
    
    
 public void saveAccount() {
    
    
 System.out.println("执行了保存");
 }

 public void updateAccount(int id) {
    
    
 System.out.println("执行了更新"+id);
 }

 public int deleteAccount() {
    
    
 System.out.println("执行了删除");
 return 0;
 }
}

4. Create tools

package com.mingqi.utils;
import org.aspectj.lang.ProceedingJoinPoint;
/**
 * 用户记录日志的工具类,里面提供公共的代码
 */
public class Logger {
    
    
 /**
 * 用于打印日志:计划让其在切入点方法执行前执行(切入点方法就是业务层方法)
 */
 public void beforePrintLog(){
    
    
 System.out.println("Logger类中的pringLog方法开始记录日志了。。。");
 }
 public void afterReturningPrintLog()
 {
    
    
 System.out.println("后置通知Logger类中的beforePrintLog方法开始记录日志了。。。");
 }
 /**
 * 异常通知
 */
 public void afterThrowingPrintLog()
 {
    
    
 System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。");

 }
 /**
 * 最终通知
 */
 public void afterPrintLog()
 {
    
    
 System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。");
 }

 /**
 * 环绕通知
 * 问题 当我们配置了环绕通知以后,切入点方法没有执行,而通知方法执行了
 * 分析: 通过对比动态代理中的环绕通知代码,发现动态代理中的环绕通知有明确的切入点方法调用,而我们的代码中没有
 * 解决: Spring 框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点的方法
 * 该接口可以作为环绕通知的参数方法,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用
 * spring中的环绕通知
 * 他是spring框架为我们提供的一种可以在代码中手动控制增强方法何时会执行的方式
 * @param pjp
 * @return
 */
 public Object aroundPringLog(ProceedingJoinPoint pjp){
    
    
 Object rtValue = null;
 try{
    
    
  Object[] args = pjp.getArgs();//得到方法执行所需的参数

  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置");

  rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)

  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置");

  return rtValue;
 }catch (Throwable t){
    
    
  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常");
  throw new RuntimeException(t);
 }finally {
    
    
  System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");
 }
 }
}

5. Create a bean 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: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">
 <!-- 配置spring的IOC,把service对象配置进来-->
 <bean id="accountSevice" class="com.mingqi.services.impl.AccountServicesImpl"></bean>
 <!-- spring 中基于xml的Aop配置步骤
  1、把通知Bean也交给spring来管理
  2、使用aop:config标签表名开始aop的配置
  3、使用aop:aspect标签表明配置切面
  id属性:是给切面提供一个唯一标识
  ref属性:是指定通知类的id
  4、在aop:aspect标签的内部使用对应的标签来配置通知的类型
  我们现在的示例是让printlog方法在切入点方法执行之前执行,所以是前置通知
  aop:before:标识前置通知
  method属性: 用于指定Logger类中的方法哪个是前置通知
  pointcut属性: 用于指定切入点表达式,该表达式的含义指的是对业务层中的哪些方法增强
  切入点表达式的写法:
   关键字:execution(表达式)
   表达式: 访问修饰符 返回值 包名.包名.包名....类名.方法名(参数列表)
   标准的写法: public void com.mingqi.service.impl.AccountServiceImpl.saveAccount()
   访问修饰符可以省略:void com.mingqi.service.impl.AccountServiceImpl.saveAccount()
   返回值可以使用通配符,标识任意返回值:* com.mingqi.service.impl.AccountServiceImpl.saveAccount()
   包名可以使用通配符,表示任意包,但是有几级包就需要写几个* *.*.*.*.*.AccountServiceImpl.saveAccount()
   包名可以使用..代表当前包及其子包:* *.AccountServiceImpl.saveAccount()
   类名和方法名都可以使用*来实现统配 * *..*.*();
   参数列表: 可以直接写数据类型:
     基本类型直接写名称:int
     引用类型写包名.类名的方式: java.lang.String
    可以使用通配符来标识任意类型,单必须有参数
    可以使用..标识有无参数均可,有参数可以是任意类型

   全通配写法:
   * *..*.*(..)
   实际开发中 切入点表达式的通常写法:
    切到业务层实现类的所有方法,* com.mingqi.service.impl.*.*(..);
  -->
 <!-- 配置Logger类-->
 <bean id="logger" class="com.mingqi.utils.Logger"></bean>
 <!--使用aop:config标签表名开始aop的配置-->
 <aop:config>
  <aop:pointcut id="pt1" expression="execution(* com.mingqi.services.impl.*.*(..))"></aop:pointcut>
  <!--使用aop:aspect标签表明配置切面-->
  <aop:aspect id="LogAdvice" ref="logger">
   <!-- 配置前置通知:在切入点方法执行之前执行
   <aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>-->

   <!-- 配置后置通知:在切入点方法正常执行之后值。它和异常通知永远只能执行一个
    <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>-->
   <!-- 配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个
    <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>-->
   <!-- 配置最终通知:无论切入点方法是否正常执行它都会在其后面执行
   <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>-->
   <!-- 配置环绕通知 详细的注释请看Logger类中-->
   <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
   </aop:aspect>
  </aop:config>
 </beans>

6. Create a test class

package com.mingqi.test;
import com.mingqi.services.IAccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringIoc {
    
    
 @Test
 public void TestAccount()
 {
    
    
 ApplicationContext ac= new ClassPathXmlApplicationContext("beam.xml");
 IAccountService accountService=(IAccountService) ac.getBean("accountSevice");
 accountService.saveAccount();
 accountService.updateAccount(22);
 accountService.deleteAccount();
 }
}

to sum up

Space is limited! Space is limited! Regarding the detailed steps of xml-based AOP in Spring, let’s talk about it...la...la...
All the relevant notes and materials introduced in the above editor have been organized into a book, whether it is Redis interview + Redis actual combat pdf, or MongDB fast Getting started + MongDB cluster security and other handwritten pdf notes, it is very easy to want to prostitution! !
——If you get it, then click like and forward to support a wave!
——It is not easy to organize, the private message password of the white whoring [666], 100% reply to share!
——I wish a bright future, continuous offers, study hard, and make progress every day!

Guess you like

Origin blog.csdn.net/p1830095583/article/details/115219536