首页 > 其他分享 >AOP解析

AOP解析

时间:2024-04-14 14:45:04浏览次数:21  
标签:创建 AOP result signature println Integer 解析 public

AOP bean 准备

1 AOP sample

1.1 创建切面

package com.gientech.aop.xml.util;

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


import java.util.Arrays;


public class LogUtil {

    public void myPointCut(){}

    public void myPointCut1(){}


    private int start(JoinPoint joinPoint){
        // 获取方法签名
        Signature signature = joinPoint.getSignature();
        // 获取参数信息
        Object[] args = joinPoint.getArgs();
        System.out.println("log----" + signature.getName() + " start execute");
        return 100;
    }

    public static void stop(JoinPoint joinPoint, Object result){
        Signature signature = joinPoint.getSignature();
        System.out.println("log----" + signature.getName() + " execute stop" + result);
    }

    public static void logException(JoinPoint joinPoint, Exception e){
        Signature signature = joinPoint.getSignature();
        System.out.println("log----" + signature.getName() + "throw new excepttion " + e.getMessage());
    }

    public static void logFinally(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("log----" + signature.getName() + " execute over");
    }

    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        Signature signature = pjp.getSignature();
        Object[] args = pjp.getArgs();
        Object result = null;
        try {
            System.out.println("log----环绕通知 start: " + signature.getName() + " method start execute, parameter is " + Arrays.asList(args));
            //通过反射的方式调用目标的方法,相当于执行method.invoke(),可以自己修改结果值
            result = pjp.proceed(args);
            System.out.println("log----环绕通知 stop: " + signature.getName() + " method execute over ");
        }catch (Throwable throwable){
            System.out.println("log----环绕异常通知 stop: " + signature.getName() + " 出现异常 ");
            throw throwable;
        }finally {
            System.out.println("log----环绕返回通知 stop: " + signature.getName() + " 方法返回结果是: "  + result);
        }
        return result;
    }

}

1.2 创建业务类

package com.gientech.aop.xml.service;

import org.springframework.stereotype.Service;


public class MyCalculator /* implements Calculator */{


    public Integer add(Integer i, Integer j) throws NoSuchMethodException{
        Integer result = i + j;
        return result;
    }


    public Integer sub(Integer i, Integer j) throws NoSuchMethodException{
        Integer result = i - j;
        return result;
    }

    public Integer mul(Integer i, Integer j) throws NoSuchMethodException{
        Integer result = i * j;
        return result;
    }

    public Integer div(Integer i, Integer j) throws NoSuchMethodException{
        Integer result = i / j;
        return result;
    }

    public Integer show(Integer i){
        System.out.println("show  ......");
        return i;
    }

}

1.3 创建配置文件

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


    <bean id="logUtil" class="com.gientech.aop.xml.util.LogUtil"></bean>
    <bean id="myCalculator" class="com.gientech.aop.xml.service.MyCalculator"></bean>
    <aop:config>
        <aop:aspect ref="logUtil">
            <aop:pointcut id="myPoint"
                          expression="execution(Integer com.gientech.aop.xml.service.MyCalculator.* (..))"/>
            <aop:around method="around" pointcut-ref="myPoint"></aop:around>
            <aop:around method="start" pointcut-ref="myPoint"></aop:around>
            <aop:before method="start" pointcut-ref="myPoint"></aop:before>
            <aop:after method="logFinally" pointcut-ref="myPoint"></aop:after>
            <aop:after-returning method="stop" pointcut-ref="myPoint" returning="result"></aop:after-returning>
            <aop:after-throwing method="logException" pointcut-ref="myPoint" throwing="e"></aop:after-throwing>
        </aop:aspect>
    </aop:config>

 </beans>

1.4 创建启动类

package com.gientech.aop.xml;

import com.gientech.aop.xml.service.MyCalculator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    public static void main(String[] args) throws Exception {
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml");
        MyCalculator bean = ac.getBean(MyCalculator.class);
        Integer result = bean.add(1,2);
        System.out.println(result);
    }
}

解析过程中注册 AspectJAwareAdvisorAutoProxyCreator。
在registerBeanPostProcessors方法中创建 AnnotationAwareAspectJAutoProxyCreator(自动代理创建器)对象。
logutil是切面对象,切面对象不需要被代理,所以logutil不需要被代理。
运行结果如下:
AOPResult

2 AOP BeanDefinition加载过程

当使用spring的aop的时候,需要进行N多个对象的创建,但是在创建过程中需要做很多判断,判断当前对象是否需要被代理,而代理之前,需要的advisor对象必须要提前创建好,才能进行后续的判断。

Aop 标签对应的类如下:

  • AspectJMethodBeforeAdvice.java: aop:before 标签对应类
  • AspectJAfterAdvice.java: aop:after 标签对应类
  • AspectJAfterReturningAdvice.java: after-returning 标签对应类
  • AspectJAfterThrowingAdvice.java:after-throwing 标签对应类
  • AspectJAroundAdvice.java: aop:around 标签对应类
  • AspectJExpressionPointcut.java: 表达式对应的类对象,eg:"execution(Integer com.gientech.aop.xml.service.MyCalculator.* (..))"

AOP BeanDefinition加载过程如图,
aop解析过程

  • 1 创建AspectJPointAdvisor#0-4,先使用器带参的构造函数进行对象的创建,但是需要将参数对象准备好,因此要创建内置包含的对象AspectJAroundAdvice
  • 2 创建AspectJAroundAdvice,也需要使用带参的构造函数进行创建,也需要提前准备好具体的参数对象,包含3个参数对象,分别是MethodLocatingFactoryBean, AspectJExpressionPointcut, SimpleBeanFactoryAwareAspectInstanceFactory。
  • 3 分别创建上述3个对象,上述3个对象的创建过程都是调用无参的构造函数,直接反射生成即可。

自动代理创建器
切面对象不需要被代理
MyCalculator是被代理对象

某个对象需要被动态代理,此对象对应的普通实例对象也是需要被创建的,只是在后续过程中普通实例对象会被替换。

标签:创建,AOP,result,signature,println,Integer,解析,public
From: https://www.cnblogs.com/zgcy123456/p/18115042

相关文章

  • SRPCore GenerateHLSL解析及其扩展
    序言在之前的项目开发HDRP的时候,就觉得绑定RT的管理就像一坨屎一样难受,改了管线RT的绑定顺序,原来的Shader输出又会有问题(主要是SV_Target顺序问题),没办法只能够在管线原来的绑定上面,重新写了一份文件,让Shader的共用Pass引用,这样就能规范不同Shaderpass的输出了。但是这只是解......
  • 大模型时代的PDF解析工具
    去年(2023年)是大模型爆发元年。但是大模型具有两个缺点:缺失私有领域知识和幻觉。缺失私有领域知识是指大模型训练时并没有企业私有数据/知识,所以无法正确回答相关问题。并且在这种情况下,大模型会一本正经地胡说八道(即幻觉),给出错误的回答。那么如何解决这两个缺点?目前主要有两种方......
  • fatfs文件系统读取剩余空间实例解析
    一前记 文件系统读取剩余内存空间并显示是一个常用的功能。这个函数是:FRESULTf_getfree(constTCHAR*path,DWORD*nclst,FATFS**fatfs);/*Getnumberoffreeclustersonthedrive*/第一个入参是文件路径,第二个参数剩余空间的指针,第三个参数是文件名。二实例......
  • APP上架流程解析
    在当今数字化时代,移动应用程序已经成为企业和个人推广业务、增加收入的重要途径之一。然而,许多开发者却面临着一个共同的问题:他们不知道如何将自己开发的应用程序上架到应用商店中。本文将深入探讨APP上架的流程,并为您提供详细的指导,以便顺利将您的App推向市场。准备上架所需......
  • DNS解析过程
    勘误一些没有说浏览器缓存的检查浏览器缓存,有且没过期的话就用如果上面失败,就查本地的hosts文件中查找是否有这个网址的映射关系,如果有则直接调用这个IP的映射进行访问如果hosts文件(/etc/hosts、C:\Windows\System32\drivers\etc\hosts)中没有,则会去找当前网络中设置的本地D......
  • Modbus 存储区 功能码 报文 解析
    存储区   输出线圈   0区  地址范围000001--065536(实际用不到所以有个短地址)00001-09999   输入线圈   1区 地址范围100001--165536                     10001-19999输入寄存器3区 地址......
  • 深入解析decltype和decltype(auto)
    decltype关键字是C++11新标准引入的关键字,它和关键字auto的功能类似,也可以自动推导出给定表达式的类型,但它和auto的语法有些不同,auto推导的表达式放在“=”的右边,并作为auto所定义的变量的初始值,而decltype是和表达式结合在一起,语法如下:decltype(expr)var;它的语法像是函数调......
  • RAG应用开发实战(01)-RAG应用框架和解析器
    1开源解析和拆分文档第三方的工具去对文件解析拆分,去将我们的文件内容给提取出来,并将我们的文档内容去拆分成一个小的chunk。常见的PDFwordmarkdown,JSON、HTML。都可以有很好的一些模块去把这些文件去进行一个东西去提取。优势支持丰富的文档类型每种文档多样化选择与......
  • C++ 引用和指针:内存地址、创建方法及应用解析
    C++引用和指针创建引用引用变量是对现有变量的“别名”,它是使用&运算符创建的:stringfood="Pizza";//食物变量string&meal=food;//对food的引用现在,我们可以使用变量名food或引用名meal来引用食物变量:cout<<food<<"\n";//输出Pizzacout<<mea......
  • 模拟SQLserver死锁现象(解析)
    SQLServer死锁是指两个或多个事务相互等待对方持有的资源而无法继续执行的情况。当两个或多个事务都持有一些资源并且试图获取其他事务持有的资源时,可能会发生死锁。这种情况下,每个事务都在等待另一个事务释放其所需的资源,导致所有涉及的事务都无法继续执行,形成了死锁。死锁通常......